#include "DeleteExpiredFolderEngine.h"

using namespace ai_matrix;

DeleteExpiredFolderEngine::DeleteExpiredFolderEngine() {}

DeleteExpiredFolderEngine::~DeleteExpiredFolderEngine() {}

APP_ERROR DeleteExpiredFolderEngine::Init()
{
    iDaysNumber_ = MyYaml::GetIns()->GetIntValue("gc_days_for_result_expire_folder");
    strResultPath_ = MyYaml::GetIns()->GetPathValue("gc_result_path");
    strLogBakPath_ = MyYaml::GetIns()->GetPathValue("gc_log_logfile_bakpath");

    LogInfo << "DeleteExpiredFolderEngine Init ok";
    return APP_ERR_OK;
}

APP_ERROR DeleteExpiredFolderEngine::DeInit()
{
    LogInfo << "DeleteExpiredFolderEngine DeInit ok";
    return APP_ERR_OK;
}

APP_ERROR DeleteExpiredFolderEngine::Process()
{
    int iRet = APP_ERR_OK;
    while (!isStop_)
    {
        std::string strTrainDate_temp = MyUtils::getins()->GetDate();

        DeletePreviousFolder(strResultPath_, strTrainDate_temp, iDaysNumber_);
        // DeletePreviousFolder(strLogBakPath_, strTrainDate_temp, iDaysNumber_);

        usleep(1000*1000*10); //每10秒执行一次
    }

    return APP_ERR_OK;
}

void DeleteExpiredFolderEngine::DeletePreviousFolder(std::string path, const std::string &date, int n_days)
{
    // 1 computer date
    std::string previous_date = getDateBeforeNDays(date, n_days);
    if (!previous_date.empty())
        std::cout << "Date before " << n_days << " days from " << date << " is: " << previous_date << std::endl;


    // 2
    std::vector<Date> subfolders;
    GetSubfolderNames(path, subfolders);
    // for (const auto &it : subfolders)
    //     std::cout << it.year << "." << it.month << "." << it.day << std::endl;

    // 3 delete
    if (path.back() != '/')
        path += "/";
    Date reference_date = StrToDate(previous_date); // 给定的参考日期
    DeleteEarlierDatesFolder(path, subfolders, reference_date);
}

// 获取某月有多少天
int DeleteExpiredFolderEngine::DaysInMonth(int year, int month)
{
    int max_days[13] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
    if (month == 2 && ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0))
    {
        max_days[2] = 29; // 闰年2月有29天
    }
    return max_days[month];
}

// 解析字符串为日期结构体
Date DeleteExpiredFolderEngine::StrToDate(const std::string &date_str)
{
    std::istringstream iss(date_str);
    int year, month, day;
    char dash;

    if (!(iss >> year >> dash && dash == '-' &&
          iss >> month >> dash && dash == '-' &&
          iss >> day))
    {
        LogError << ("Invalid date format") << ":" << date_str;
    }
    return {year, month, day};
}

// 减去指定天数
void DeleteExpiredFolderEngine::SubtractDays(Date &date, int n_days)
{
    while (n_days > 0)
    {
        date.day--;
        n_days--;
        if (date.day == 0)
        {
            if (--date.month == 0)
            {
                --date.year;
                date.month = 12;
            }
            int max_days = DaysInMonth(date.year, date.month);
            date.day = max_days;
        }
    }
}

// 格式化日期结构体为字符串
std::string DeleteExpiredFolderEngine::DateToStr(const Date &date)
{
    std::ostringstream oss;
    oss << date.year << "-" << std::setfill('0') << std::setw(2) << date.month << "-" << std::setw(2) << date.day;
    return oss.str();
}

// 主要功能函数，接收一个日期字符串和一个整数n，返回n天前的日期字符串
std::string DeleteExpiredFolderEngine::getDateBeforeNDays(const std::string &input_date, int n_days)
{
    try
    {
        Date date = StrToDate(input_date);
        SubtractDays(date, n_days);
        return DateToStr(date);
    }
    catch (const std::exception &e)
    {
        LogError << "Error: " << e.what();
        return "";
    }
}

void DeleteExpiredFolderEngine::GetSubfolderNames(std::string &directory, std::vector<Date> &folder_names)
{
    if (directory.back() != '/')
        directory += "/";
    DIR *dir;
    struct dirent *ent;
    if ((dir = opendir(directory.c_str())) != nullptr)
    {
        while ((ent = readdir(dir)) != nullptr)
        {
            // 排除"."和".."
            if (ent->d_type == DT_DIR && ent->d_name[0] != '.' && ent->d_name != "best")
            {
                folder_names.push_back(StrToDate(ent->d_name));
            }
        }
        closedir(dir);
    }
    else
    {
        LogError << "Unable to open directory: " << directory;
    }
}

void DeleteExpiredFolderEngine::DeleteFolder(const std::string directory)
{
    std::string command = "rm -rf " + directory;
    int result = system(command.c_str());

    if (result != 0)
        std::cout << "Failed to remove directory recursively: " << directory << std::endl;
    else
        std::cout << "delete folder successfully : " << directory << std::endl;
}

// 删除向量中小于指定日期的所有元素
void DeleteExpiredFolderEngine::DeleteEarlierDatesFolder(std::string &path, std::vector<Date> &subfolders, const Date &reference_date)
{
    if (path.back() != '/')
        path += "/";
    for (const Date &cur : subfolders)
    {
        // bool flag = false;
        if (cur.year < reference_date.year)
        {
            DeleteFolder(path + DateToStr(cur));
        }
        else if (cur.year == reference_date.year && cur.month < reference_date.month)
        {
            DeleteFolder(path + DateToStr(cur));
        }
        else if (cur.year == reference_date.year && cur.month == reference_date.month && cur.day < reference_date.day)
        {
            DeleteFolder(path + DateToStr(cur));
        }
    }
}

// void DeleteExpiredFolderEngine::PushData(const std::string &strPort, const std::shared_ptr<ProcessData> &pSaveImgData)
// {
//     while (true)
//     {
//         int iRet = outputQueMap_[strPort]->push(std::static_pointer_cast<void>(pSaveImgData));
//         if (iRet != 0)
//         {
//             LogDebug << "sourceid:" << pSaveImgData->iDataSource << " frameid:" << pSaveImgData->iFrameId << " push fail iRet:" << iRet;
//             if (iRet == 2)
//             {
//                 usleep(10000); // 10ms
//                 continue;
//             }
//         }
//         break;
//     }
// }
