import json
import os
import socket
import sys
import tempfile
from pathlib import Path
from platform import uname

import toml
from datamodel_code_generator import InputFileType, generate
from dotenv import load_dotenv


def is_windows():
    return sys.platform == "win32"


def is_mac():
    return sys.platform == "darwin"


def is_wsl():
    return "microsoft-standard" in uname().release


def is_linux():
    return sys.platform == "linux"


def get_hostname():
    return socket.gethostname()


class ConfigLoader:
    def __init__(self):
        self.HOSTNAME = get_hostname()
        self.MODE = os.environ.get("ENV", "")
        if self.MODE:
            pass
        elif is_windows() or is_mac() or is_wsl():
            self.MODE = "local"
        elif "dev" in self.HOSTNAME:
            self.MODE = "dev"
        elif "test" in self.HOSTNAME:
            self.MODE = "test"
        elif "prod" in self.HOSTNAME or is_linux:
            self.MODE = "prod"
        self.config_dict = {}

    def load_base_config(self):
        """
        加载基础配置文件
        """
        common_file_path = os.path.join(os.getcwd(), "config", "config_base.toml")
        self.config_dict = toml.load(common_file_path)

    def load_env_config(self):
        """
        加载环境配置文件
        """
        load_dotenv()  # 默认读取当前工作目录下的 .env
        env_file_path = os.getenv("ENV_FILE_PATH")
        if env_file_path:
            env_file_path = Path(env_file_path).expanduser().resolve()
        else:
            env_file_path = os.path.join(os.getcwd(), "config", f"config_{self.MODE}.toml")
        env_config = toml.load(env_file_path)
        # 配置项如果存在则覆盖
        for section, settings in env_config.items():
            if section in self.config_dict:
                self.config_dict[section].update(settings)
            else:
                self.config_dict[section] = settings

    def load_custom_config(self):
        """
        加载自定义配置
        """
        # 公共配置
        APP_NAME = self.config_dict["app"]["name"]
        # 获取用户目录
        HOME_DIR = os.path.expanduser("~")
        win_drive = "D:\\"  # Windows 路径
        if os.path.exists(win_drive) is False:
            win_drive = "C:\\"
        DATA_DIR_DICT = {
            "win32": os.path.join(f"{win_drive}data\\appdata", APP_NAME),
            "darwin": os.path.join(f"{HOME_DIR}/data/appdata", APP_NAME),  # mac无法创建/data
            "default": os.path.join("/data/appdata", APP_NAME),
        }
        MAIN_DIR = DATA_DIR_DICT.get(sys.platform, DATA_DIR_DICT["default"])

        # 拼接路径
        DATA_DIR = os.path.join(MAIN_DIR, self.config_dict["dirs"]["data_dir"])
        LOGS_DIR = os.path.join(MAIN_DIR, self.config_dict["dirs"]["logs_dir"])
        TEMP_DIR = os.path.join(MAIN_DIR, self.config_dict["dirs"]["temp_dir"])
        OUT_DIR = os.path.join(MAIN_DIR, self.config_dict["dirs"]["out_dir"])
        APP_LOG_PATH = os.path.join(LOGS_DIR, self.config_dict["common"]["app_log_path"])

        self.config_dict["dirs"]["data_path"] = DATA_DIR
        self.config_dict["dirs"]["logs_path"] = LOGS_DIR
        self.config_dict["dirs"]["temp_path"] = TEMP_DIR
        self.config_dict["dirs"]["out_path"] = OUT_DIR
        self.config_dict["dirs"]["app_log_path"] = APP_LOG_PATH

        os.makedirs(LOGS_DIR, exist_ok=True)
        for dir_name in [DATA_DIR, LOGS_DIR, TEMP_DIR, OUT_DIR]:
            os.makedirs(dir_name, exist_ok=True)

    def get_config(self):
        self.load_base_config()
        self.load_env_config()
        self.load_custom_config()

        json_str = json.dumps(self.config_dict, indent=4)
        output_file = os.path.join(os.getcwd(), "config", "models.py")
        with tempfile.NamedTemporaryFile("w", delete=False) as temp_file:
            temp_file_path = temp_file.name
            generate(
                input_=json_str,
                input_file_type=InputFileType.Json,  # 使用 'Json' 作为输入文件类型
                output=Path(temp_file_path),  # 输出到临时文件路径
                disable_timestamp=True,
                # formatters=[],  # 禁用自动格式化，避免 FutureWarning
            )
            with open(temp_file_path, "r") as temp_f:
                generated_code = temp_f.read()

            # NamedTemporaryFile设置delete=Ture，在 windows 下可能会没有权限，所以最后删除
            os.unlink(temp_file_path)

        if os.path.exists(output_file) is False:
            with open(output_file, "w") as f:
                f.write(generated_code)
            msg = "配置已生成"
        else:
            with open(output_file, "r") as f:
                existing_code = f.read()

            if existing_code != generated_code:
                # 如果代码有变化，则覆盖写入
                with open(output_file, "w") as f:
                    f.write(generated_code)
                msg = "配置已更新"
            else:
                msg = "配置无更新"

        from config.models import Model

        settings = Model.model_validate(self.config_dict)

        print(f"环境初始化: load {self.MODE}, {msg}")

        return settings


if __name__ == "__main__":
    config_loader = ConfigLoader()

    settings = config_loader.get_config()
    print(settings)
