import sys
from pathlib import Path

from dotenv import load_dotenv


BACKEND_DIR = Path(__file__).resolve().parent.parent
REPO_DIR = BACKEND_DIR
if str(BACKEND_DIR) not in sys.path:
    sys.path.insert(0, str(BACKEND_DIR))

load_dotenv(REPO_DIR / ".env")

from app.settings import (  # noqa: E402
    APP_ALLOWED_HOSTS,
    APP_ENABLE_AUTH,
    APP_ENV,
    APP_SESSION_SECRET,
    BERNOULLI_LOGIN_PASSWORD,
    BERNOULLI_LOGIN_URL,
    BERNOULLI_LOGIN_USERNAME,
    BERNOULLI_PARAMETROS_PAYLOAD,
    BERNOULLI_PARAMETROS_URL,
    CAMINHO_ICONE,
    CAMINHO_MODELO_CARTAO,
    KEEPEDU_API_KEY,
    KEEPEDU_INSTITUTE,
    KEEPEDU_LOGIN_URL,
    PASTA_BACKUPS,
    PASTA_LOGS,
    PASTA_PROCESSAMENTOS,
    PASTA_RUNTIME,
    PASTA_UPLOADS_TEMP,
    garantir_pastas,
)


def check_ok(message):
    print(f"[OK] {message}")


def check_warn(message):
    print(f"[WARN] {message}")


def check_fail(message):
    print(f"[FAIL] {message}")


def is_placeholder(value, placeholders):
    texto = str(value or "").strip()
    if not texto:
        return True
    return texto.lower() in {item.lower() for item in placeholders}


def main():
    falhas = 0
    avisos = 0

    env_file = REPO_DIR / ".env"
    if env_file.exists():
        check_ok(".env encontrado")
    else:
        check_fail(".env nao encontrado na raiz do projeto")
        falhas += 1

    if APP_ENV == "production":
        check_ok("APP_ENV configurado como production")
    else:
        check_fail(f"APP_ENV atual: {APP_ENV}. O recomendado para implantacao e production")
        falhas += 1

    if APP_ENABLE_AUTH:
        check_ok("Autenticacao habilitada")
    else:
        check_warn("APP_ENABLE_AUTH esta false; a aplicacao ficara sem login")
        avisos += 1

    if APP_ENABLE_AUTH:
        if is_placeholder(APP_SESSION_SECRET, {"omrcheck-session-secret-change-me", "troque-esta-chave-de-sessao-longa-e-aleatoria"}):
            check_fail("APP_SESSION_SECRET ainda parece padrao")
            falhas += 1
        else:
            check_ok("APP_SESSION_SECRET personalizado")

        if not KEEPEDU_LOGIN_URL:
            check_fail("KEEPEDU_LOGIN_URL nao configurada; login da interface nao funcionara")
            falhas += 1
        else:
            check_ok(f"Login KeepEdu configurado ({KEEPEDU_LOGIN_URL})")

    allowed_hosts = [item.strip() for item in APP_ALLOWED_HOSTS if str(item).strip()]
    placeholders_hosts = {"localhost", "127.0.0.1"}
    hosts_validos = [host for host in allowed_hosts if host.lower() not in placeholders_hosts]
    if hosts_validos:
        check_ok(f"APP_ALLOWED_HOSTS configurado para implantacao: {', '.join(hosts_validos)}")
    else:
        check_fail("APP_ALLOWED_HOSTS ainda esta apenas com localhost/127.0.0.1")
        falhas += 1

    if KEEPEDU_API_KEY.strip():
        check_ok("KEEPEDU_API_KEY preenchida")
    else:
        check_fail("KEEPEDU_API_KEY nao preenchida")
        falhas += 1

    if KEEPEDU_INSTITUTE.strip():
        check_ok("KEEPEDU_INSTITUTE preenchido")
    else:
        check_fail("KEEPEDU_INSTITUTE nao preenchido")
        falhas += 1

    bernoulli_login_configurado = bool(
        BERNOULLI_LOGIN_URL.strip()
        and BERNOULLI_LOGIN_USERNAME.strip()
        and BERNOULLI_LOGIN_PASSWORD.strip()
    )
    bernoulli_parametros_configurado = bool(
        BERNOULLI_PARAMETROS_URL.strip() and BERNOULLI_PARAMETROS_PAYLOAD
    )
    if bernoulli_login_configurado:
        if bernoulli_parametros_configurado:
            check_ok("Bernoulli com fluxo login + parametros configurado")
        else:
            check_ok("Bernoulli com login automatico configurado")
    else:
        check_warn("Bernoulli sem autenticacao configurada; consultas RMB podem falhar")
        avisos += 1

    if CAMINHO_MODELO_CARTAO.exists():
        check_ok("Template OMR encontrado")
    else:
        check_fail(f"Template OMR ausente em {CAMINHO_MODELO_CARTAO}")
        falhas += 1

    if CAMINHO_ICONE.exists():
        check_ok("Icone da aplicacao encontrado")
    else:
        check_warn("Icone da aplicacao nao encontrado")
        avisos += 1

    try:
        garantir_pastas()

        from app.db import ENGINE, mysql_habilitado

        if mysql_habilitado():
            from app.migrations import run_migrations, status_migrations

            if ENGINE is None:
                check_fail("ENGINE MySQL nao inicializado; verifique MYSQL_* no .env")
                falhas += 1
            else:
                try:
                    from sqlalchemy import text

                    with ENGINE.connect() as conn:
                        conn.execute(text("SELECT 1"))
                    executadas = run_migrations(ENGINE)
                    info = status_migrations(ENGINE)
                    if info["pendentes"]:
                        check_fail(f"Migrations pendentes: {', '.join(info['pendentes'])}")
                        falhas += 1
                    else:
                        if executadas:
                            check_ok(f"Migrations aplicadas agora: {', '.join(executadas)}")
                        check_ok(
                            f"Schema MySQL atualizado ({len(info['aplicadas'])}/{info['total']} migrations)"
                        )
                except Exception as erro:
                    check_fail(f"Nao foi possivel conectar ou migrar o MySQL: {erro}")
                    falhas += 1
        else:
            check_ok("MYSQL_ENABLED=false; persistencia operacional usa arquivos locais")

        check_ok(f"Pastas operacionais verificadas em {PASTA_PROCESSAMENTOS.parent}")
        check_ok(f"Logs em {PASTA_LOGS}")
        check_ok(f"Backups em {PASTA_BACKUPS}")
        check_ok(f"Runtime em {PASTA_RUNTIME}")
        check_ok(f"Uploads temporarios em {PASTA_UPLOADS_TEMP}")
    except Exception as erro:
        check_fail(f"Nao foi possivel preparar as pastas operacionais: {erro}")
        falhas += 1

    print("")
    print(f"Resumo: {falhas} falha(s), {avisos} aviso(s)")

    if falhas:
        print("Preflight reprovado. Corrija as falhas antes da implantacao.")
        raise SystemExit(1)

    print("Preflight aprovado para seguir com a implantacao.")


if __name__ == "__main__":
    main()
