import json
from importlib.metadata import distribution
from importlib.util import find_spec
from pathlib import Path
from typing import Mapping

from nyahome.cli.cli import console
from nyahome.database.engine import db_driver_available, db_type_allowlist


class CliWarning:
    def __init__(self) -> None:
        self.counter = 0

    def info(self, description: str) -> None:
        console.print(f"INFO      - {description}")

    def warning(self, description: str) -> None:
        self.counter += 1
        console.print(f"[yellow]WARNING {self.counter}[/yellow] - {description}")


cw = CliWarning()


def check_database_connector() -> dict[str, str]:
    """
    检查是否安装用于数据库连接的各种驱动库。只有安装对应的驱动库之后才可以连接到对应的数据库。

    Returns:
        {驱动库: 可用状态描述}
    """

    def _(value: bool, description: str) -> str:
        return f"{'[green]可用[/green]' if value else '[yellow]不可用[/yellow]'} - {description}"

    result: dict[str, str] = {
        "sqlite3": _(bool(find_spec("sqlite3")), "Python 标准库，支持 sqlite"),
        "pymysql": _(bool(find_spec("pymysql")), "社区维护的 MySQL 驱动库"),
        "psycopg": _(bool(find_spec("psycopg")), "更先进的 PostgreSQL 驱动库"),
    }

    return result


def check_database_type(environ: Mapping[str, str | None]) -> None:
    db_type = environ.get("NYAHOME_DB_TYPE")
    db_driver = environ.get("NYAHOME_DB_DRIVER")
    db_name = environ.get("NYAHOME_DB_NAME")
    db_user = environ.get("NYAHOME_DB_USER")
    db_password = environ.get("NYAHOME_DB_PASSWORD")
    db_host = environ.get("NYAHOME_DB_HOST")
    db_port = environ.get("NYAHOME_DB_PORT")

    if not db_type:
        cw.warning("NYAHOME_DB_TYPE 未设置，将回退到默认数据库 sqlite。")
    elif db_type not in db_type_allowlist:
        cw.warning(f"NYAHOME_DB_TYPE 的值 {db_type} 不受 NyaHome 官方支持。")

    if not db_driver:
        cw.warning("NYAHOME_DB_DRIVER 未设置，将使用 SQLModel 的默认驱动库。")
    elif not find_spec(db_driver):
        cw.warning(f"NYAHOME_DB_DRIVER 的值 {db_driver} 未在当前 NyaHome 中安装。")
    elif db_type and (db_driver not in db_driver_available.get(db_type, [])):
        cw.warning(f"NYAHOME_DB_DRIVER 的值 {db_driver} 是为数据库 {db_type} 准备的吗？")

    if db_driver and db_type != "sqlite":  # 对于 sqlite 数据库，不需要设置凭证
        if not db_name:
            cw.warning("NYAHOME_DB_NAME 未设置，将使用 [cyan]nyahome[/cyan] 作为默认值。")
        if not db_user:
            cw.warning("NYAHOME_DB_USER 未设置，将使用 [cyan]nyahome[/cyan] 作为默认值。")
        if not db_password:
            cw.warning("NYAHOME_DB_PASSWORD 未设置，将使用 [cyan]nyahome[/cyan] 作为默认值。")
        if not db_host:
            cw.warning("NYAHOME_DB_HOST 未设置，将使用 [cyan]localhost[/cyan] 作为默认值。")
        if not db_port:
            cw.warning("NYAHOME_DB_PORT 未设置，将使用 [cyan]3306[/cyan] 作为默认值。")
        cw.info("自检未检查数据库状态是否可用。")
    else:
        cw.info("使用 sqlite 数据库，跳过数据库凭证检查。")


def check_uvicorn(environ: Mapping[str, str | None]) -> None:
    un_host = environ.get("NYAHOME_UVICORN_HOST")
    un_port = environ.get("NYAHOME_UVICORN_PORT")
    un_reload = environ.get("NYAHOME_UVICORN_RELOAD")

    if not un_host:
        cw.warning("NYAHOME_UVICORN_HOST 未设置，将使用 [cyan]0.0.0.0[/cyan] 作为默认值。")
    if not un_port:
        cw.warning("NYAHOME_UVICORN_PORT 未设置，将使用 [cyan]9000[/cyan] 作为默认值。")
    if not un_reload:
        cw.warning("NYAHOME_UVICORN_RELOAD 未设置，将使用 [cyan]false[/cyan] 作为默认值。")
    else:
        if un_reload in ["True", "true", "1"]:
            cw.warning("NYAHOME_UVICORN_RELOAD 设置为 [cyan]true[/cyan]，在生产环境中不应如此。")


def check_nyahome_status() -> None:
    # 检查是否以可编辑模式安装 NyaHome
    dist = distribution("nyahome")
    try:
        f = dist.read_text("direct_url.json")
        if f:
            data = json.loads(f)
            if data.get("dir_info", {}).get("editable", False):
                cw.warning("当前 NyaHome 以可编辑模式安装。在生产环境中不应如此。")
    except Exception:
        pass

    # 检查 NyaHome 是否受 git 管理
    git_dir = Path.cwd() / ".git"
    if git_dir.is_dir():
        cw.warning("当前 NyaHome 受版本控制系统管理。在生产环境中不应如此。")


LOGGING_YAML_CONTENT = """version: 1
disable_existing_loggers: false

formatters:
  default:
    "()": uvicorn.logging.DefaultFormatter
    fmt: "%(asctime)s | %(levelprefix)s %(name)s | %(message)s"
    use_colors: true

  access:
    "()": uvicorn.logging.AccessFormatter
    fmt: '%(asctime)s | %(client_addr)s - "%(request_line)s" %(status_code)s'
    use_colors: true

handlers:
  default:
    formatter: default
    class: logging.StreamHandler
    stream: ext://sys.stderr

  access:
    formatter: access
    class: logging.StreamHandler
    stream: ext://sys.stdout

  file:
    formatter: default
    class: logging.handlers.RotatingFileHandler
    filename: .nyahome/app.log
    maxBytes: 10485760
    backupCount: 5
    encoding: utf8

loggers:
  uvicorn:
    handlers: [ default, file ]
    level: INFO
    propagate: false

  uvicorn.error:
    handlers: [ default, file ]
    level: INFO
    propagate: false

  uvicorn.access:
    handlers: [ access, file ]
    level: INFO
    propagate: false

  nyahome:
    handlers: [ default, file ]
    level: DEBUG
    propagate: false"""
