#pragma once

#include <iostream>
#include <fstream>
#include <sstream>
#include <string>
#include <map>
#include <vector>
#include <algorithm>
#include <cctype>
#include <ctime>
#include <iomanip>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <pwd.h>
#include <mutex>

struct traffic_light_config
{
    /* data */
    uint16_t id;
    std::string name;
    std::string type;
    std::vector<uint16_t> do_addr;
    std::vector<std::string> color;
};

struct roadside_info_config
{
    std::string id;
    std::string topic;
    double longitude;
    double latitude;
    double altitude;
    uint32_t isLight;
    bool isManualLane;
    uint16_t lightState;
};


struct traffic_light_status_config
{
    /* data */
    uint16_t id;
    std::string color;
};

struct traffic_mode_config
{
    uint16_t id;
    std::vector<traffic_light_status_config> lights;
};

// INI 配置文件管理类
class Barrier_Gate_Log {
private:
    std::string filename;
    std::map<std::string, std::map<std::string, std::string>> data;
    bool file_exists = false;
    std::string log_file;

    // 去除字符串两端的空白字符
    static std::string trim(const std::string &str)
    {
        size_t start = str.find_first_not_of(" \t\r\n");
        size_t end = str.find_last_not_of(" \t\r\n");
        if (start == std::string::npos)
            return "";
        return str.substr(start, end - start + 1);
    }

    // 检查字符串是否以指定前缀开头
    static bool starts_with(const std::string &str, const std::string &prefix)
    {
        return str.size() >= prefix.size() &&
               str.compare(0, prefix.size(), prefix) == 0;
    }

    // 获取当前时间字符串
    static std::string current_time()
    {
        auto now = std::chrono::system_clock::now();
        std::time_t now_c = std::chrono::system_clock::to_time_t(now);
        std::tm now_tm = *std::localtime(&now_c);

        std::ostringstream oss;
        oss << std::put_time(&now_tm, "%Y-%m-%d %H:%M:%S");

        auto ms = std::chrono::duration_cast<std::chrono::milliseconds>(
                      now.time_since_epoch()) %
                  1000;
        oss << '.' << std::setfill('0') << std::setw(3) << ms.count();

        return oss.str();
    }


    // 确保目录存在
    bool ensure_directory_exists(const std::string &path)
    {
        size_t pos = 0;
        std::string dir;

        while ((pos = path.find_first_of('/', pos + 1)) != std::string::npos)
        {
            dir = path.substr(0, pos);
            if (dir.empty())
                continue; // 跳过根目录

            struct stat st;
            if (stat(dir.c_str(), &st) != 0)
            {
                // 目录不存在，创建它
                if (mkdir(dir.c_str(), 0755) != 0 && errno != EEXIST)
                {
                    log("创建目录失败: " + dir);
                    return false;
                }
            }
            else if (!S_ISDIR(st.st_mode))
            {
                log("路径不是目录: " + dir);
                return false;
            }
        }
        return true;
    }

    // 解析一行INI内容
    void parse_line(const std::string &line, std::string &current_section)
    {
        std::string trimmed = trim(line);

        // 跳过空行和注释
        if (trimmed.empty() || starts_with(trimmed, "#") ||
            starts_with(trimmed, ";"))
        {
            return;
        }

        // 处理节
        if (trimmed.front() == '[' && trimmed.back() == ']')
        {
            current_section = trim(trimmed.substr(1, trimmed.size() - 2));
            return;
        }

        // 处理键值对
        size_t pos = trimmed.find('=');
        if (pos != std::string::npos)
        {
            std::string key = trim(trimmed.substr(0, pos));
            std::string value = trim(trimmed.substr(pos + 1));

            // 处理带引号的值
            if (!value.empty() && value.front() == '"' && value.back() == '"')
            {
                value = value.substr(1, value.size() - 2);
            }

            data[current_section][key] = value;
        }
    }

public:

  // 记录日志
    void log(const std::string &message)
    {
        if (log_file.empty())
            return;
        std::ofstream log_stream(log_file, std::ios::app);
        if (log_stream.is_open())
        {
            // 移动指针到文件末尾
            log_stream.seekp(0, std::ios::end);
            // 获取文件大小
            long long fileSize = log_stream.tellp();
            if(fileSize>200*1024*1024)
            {
                log_stream.close();
                log_stream.clear();
                log_stream.open(log_file, std::ios::trunc);
            }
            log_stream << "[" << current_time() << "] " << message << "\n";
        }
    }

    // 构造函数
    Barrier_Gate_Log(const std::string &file) : filename(file)
    {
        struct stat st;
        if (stat(filename.c_str(), &st) == 0)
        {
            file_exists = true;
            log("INI文件存在: " + filename);
        }
        else
        {
            log("INI文件不存在: " + filename);
        }
    }

    // 设置日志文件
    void set_log_file(const std::string &inlog)
    {
        log_file = inlog;
        log("日志文件设置为: " + inlog);
    }

    // 检查INI文件是否存在
    bool exists() const
    {
        return file_exists;
    }

    // 创建INI文件
    bool create()
    {
        if (file_exists)
        {
            log("INI文件已存在: " + filename);
            return false;
        }

        // 确保目录存在
        if (!ensure_directory_exists(filename))
        {
            log("无法创建目录路径: " + filename);
            return false;
        }

        std::ofstream file(filename);
        if (!file)
        {
            log("无法创建INI文件: " + filename + " - ");
            return false;
        }

        // 写入默认配置
        file << "# Linux INI 配置文件 记录一段时间内程序启动次数  \n";
        file << "# 创建时间: " << current_time() << "\n";
        file << "# 格式说明:\n";
        file << "#   [Section] 表示配置节\n";
        file << "#   key = value 表示键值对\n";
        file << "#   以#或;开头的行是注释\n\n";


        auto now = std::chrono::system_clock::now();
         // 转换为时间戳（毫秒）
        uint64_t timestamp_seconds = std::chrono::duration_cast<std::chrono::milliseconds>(now.time_since_epoch()).count();


        file << "[General]\n";
        file << "app_name = Light_control\n";
        file << "version = 1.0.0\n";
        file << "LaunchTimes = " <<1<< "\n";
        file << "LaunchTimestamp = " << timestamp_seconds << "\n";

        file.close();
        file_exists = true;
        log("INI文件已创建: " + filename);
        return true;
    }

    // 加载INI文件
    bool load()
    {
        if (!file_exists)
        {
            log("INI文件不存在: " + filename);
            return false;
        }

        std::ifstream file(filename);
        if (!file)
        {
            log("无法打开INI文件: " + filename + " - ");
            return false;
        }

        data.clear();
        std::string line;
        std::string current_section = "General";
        while (std::getline(file, line))
        {
            parse_line(line, current_section);
            std::cout << "getline...\n";
        }
        file.close();
        log("INI文件已加载: " + filename);
        return true;
    }

    // 保存INI文件
    bool save()
    {
        if (!file_exists)
        {
            log("INI文件不存在: " + filename);
            return false;
        }

        // 备份原文件
        std::string backup = filename + ".bak";
        if (std::rename(filename.c_str(), backup.c_str()) != 0)
        {
            log("创建备份失败: ");
        }
        else
        {
            log("已创建备份: " + backup);
        }

        std::ofstream file(filename);
        if (!file)
        {
            log("无法写入INI文件: " + filename + " - ");
            // 恢复备份
            std::rename(backup.c_str(), filename.c_str());
            return false;
        }

        file << "# Linux INI 配置文件\n";
        file << "# 最后修改时间: " << current_time() << "\n";
        file << "# 用户: " << getlogin() << "\n\n";

        for (const auto &section : data)
        {
            file << "[" << section.first << "]\n";
            for (const auto &key_value : section.second)
            {
                file << key_value.first << " = " << key_value.second << "\n";
            }
            file << "\n";
        }

        file.close();
        log("INI文件已保存: " + filename);
        return true;
    }

    // 获取配置值
    std::string get_value(const std::string &section, const std::string &key, const std::string &default_value = "")
    {
        auto sec_it = data.find(section);
        if (sec_it == data.end())
        {
            log("获取配置值失败 - 节不存在: [" + section + "] " + key);
            return default_value;
        }

        auto key_it = sec_it->second.find(key);
        if (key_it == sec_it->second.end())
        {
            log("获取配置值失败 - 键不存在: [" + section + "] " + key);
            return default_value;
        }

        log("获取配置值: [" + section + "] " + key + " = " + key_it->second);
        return key_it->second;
    }

    // 获取整数值
    uint64_t get_int(const std::string &section, const std::string &key, int default_value = 0)
    {
        std::string value = get_value(section, key, "");
        if (value.empty())
            return default_value;

        try
        {
            //return std::stoi(value);
            char *endptr = nullptr;
            errno = 0; // 重置错误标志
            unsigned long long intvalue = std::strtoull(value.c_str(), &endptr, 10);
            return static_cast<uint64_t>(intvalue);
        }
        catch (...)
        {
            log("转换整数值失败: [" + section + "] " + key + " = " + value);
            return default_value;
        }
    }

    // 获取浮点数值
    double get_double(const std::string &section, const std::string &key, double default_value = 0.0)
    {
        std::string value = get_value(section, key, "");
        if (value.empty())
            return default_value;

        try
        {
            return std::stod(value);
        }
        catch (...)
        {
            log("转换浮点数值失败: [" + section + "] " + key + " = " + value);
            return default_value;
        }
    }

    // 获取布尔值
    bool get_bool(const std::string &section, const std::string &key, bool default_value = false)
    {
        std::string value = get_value(section, key, "");
        if (value.empty())
            return default_value;

        // 转换为小写比较
        std::string lower_value;
        std::transform(value.begin(), value.end(), std::back_inserter(lower_value),
                       [](unsigned char c)
                       { return std::tolower(c); });

        if (lower_value == "true" || lower_value == "yes" || lower_value == "1")
        {
            return true;
        }
        else if (lower_value == "false" || lower_value == "no" || lower_value == "0")
        {
            return false;
        }
        else
        {
            log("转换布尔值失败: [" + section + "] " + key + " = " + value);
            return default_value;
        }
    }

    // 设置配置值
    void set_value(const std::string &section, const std::string &key,
                   const std::string &value)
    {
        // std::lock_guard<std::mutex> lock(mtx);

        std::string old_value = get_value(section, key, "");
        data[section][key] = value;
        log("设置配置值: [" + section + "] " + key +
            " = " + value + " (原值: " + old_value + ")");
    }

    // 设置整数值
    void set_int(const std::string &section, const std::string &key, uint64_t value)
    {
        set_value(section, key, std::to_string(value));
    }

    // 设置浮点数值
    void set_double(const std::string &section, const std::string &key, double value)
    {
        set_value(section, key, std::to_string(value));
    }

    // 设置布尔值
    void set_bool(const std::string &section, const std::string &key, bool value)
    {
        set_value(section, key, value ? "true" : "false");
    }

    // 删除配置项
    bool remove_key(const std::string &section, const std::string &key)
    {
        auto sec_it = data.find(section);
        if (sec_it == data.end())
        {
            log("删除配置项失败 - 节不存在: [" + section + "] " + key);
            return false;
        }

        if (sec_it->second.erase(key) > 0)
        {
            log("已删除配置项: [" + section + "] " + key);
            return true;
        }

        log("删除配置项失败 - 键不存在: [" + section + "] " + key);
        return false;
    }

    // 删除配置节
    bool remove_section(const std::string &section)
    {
        if (data.erase(section) > 0)
        {
            log("已删除配置节: [" + section + "]");
            return true;
        }

        log("删除配置节失败 - 节不存在: [" + section + "]");
        return false;
    }

    // 获取所有配置节
    std::vector<std::string> get_sections()
    {
        std::vector<std::string> sections;
        for (const auto &section : data)
        {
            sections.push_back(section.first);
        }
        return sections;
    }

    // 获取指定节的所有键
    std::vector<std::string> get_keys(const std::string &section)
    {
        std::vector<std::string> keys;
        auto sec_it = data.find(section);
        if (sec_it != data.end())
        {
            for (const auto &key_value : sec_it->second)
            {
                keys.push_back(key_value.first);
            }
        }
        return keys;
    }

    // 检查配置节是否存在
    bool section_exists(const std::string &section)
    {
        return data.find(section) != data.end();
    }

    // 检查配置项是否存在
    bool key_exists(const std::string &section, const std::string &key)
    {
        auto sec_it = data.find(section);
        if (sec_it == data.end())
            return false;
        return sec_it->second.find(key) != sec_it->second.end();
    }

    // 显示所有配置
    void display()
    {
        std::cout << "\nINI 文件内容 (" << filename << "):\n";
        std::cout << "========================================\n";

        for (const auto &section : data)
        {
            std::cout << "[" << section.first << "]\n";
            for (const auto &key_value : section.second)
            {
                std::cout << "  " << key_value.first << " = " << key_value.second << "\n";
            }
            std::cout << "\n";
        }

        std::cout << "========================================\n";
        log("显示INI文件内容");
    }
};
