"""Configuração única para Passenger e cron; não depende do diretório de execução."""

import fcntl
import json
import os
import secrets
from pathlib import Path
from urllib.parse import urlparse

ROOT = Path(__file__).resolve().parent


def load_server_config(root=None):
    root = Path(root or ROOT).resolve()
    file = root / "server_config.json"
    settings = json.loads(file.read_text(encoding="utf-8")) if file.exists() else {}
    if not isinstance(settings, dict):
        raise ValueError("server_config.json deve conter um objeto JSON.")
    if file.exists():
        file.chmod(0o600)
    public_url = os.getenv("SITE_URL") or settings.get(
        "site_url", "https://app.leanmarket.com.br"
    )
    p = urlparse(public_url)
    if (
        p.scheme != "https"
        or not p.hostname
        or p.username
        or p.password
        or p.path not in ("", "/")
        or p.query
        or p.fragment
        or p.port not in (None, 443)
    ):
        raise ValueError("site_url deve ser a raiz HTTPS de um subdomínio dedicado.")
    install_token = os.getenv("INSTALL_TOKEN") or settings.get("install_token", "")
    if install_token and (
        not isinstance(install_token, str)
        or len(install_token) < 24
        or install_token.startswith("SUBSTITUA")
    ):
        raise ValueError(
            "Escolha um install_token privado de pelo menos 24 caracteres ou deixe vazio até configurar."
        )
    env = settings.get("environment", {})
    if not isinstance(env, dict):
        raise ValueError("environment deve ser um objeto JSON.")
    prefixes = ("META_", "WA_TOKEN_COMPANY_", "WEBHOOK_")
    for k, v in env.items():
        if (
            not isinstance(k, str)
            or not k.startswith(prefixes)
            or not isinstance(v, str)
        ):
            raise ValueError(
                "environment aceita somente configurações de integração META_, WA_TOKEN_COMPANY_ ou WEBHOOK_."
            )
        os.environ.setdefault(k, v)
    data = Path(os.getenv("CONVERSA_DATA_DIR") or settings.get("data_dir", "instance"))
    if not data.is_absolute():
        data = root / data
    data = data.resolve()
    if data in (root, Path.home().resolve(), Path("/")) or data in root.parents:
        raise ValueError(
            "Escolha uma pasta privada específica, como instance; não use a raiz do projeto ou da conta."
        )
    if "public_html" in data.parts:
        raise ValueError("Mova a pasta privada e o projeto para fora de public_html.")
    data.mkdir(parents=True, exist_ok=True, mode=0o700)
    data.chmod(0o700)
    # O lock vale entre processos Passenger e entre inicializações simultâneas.
    with (data / "bootstrap.lock").open("a+") as lock:
        fcntl.flock(lock, fcntl.LOCK_EX)
        secret_file = data / "session-secret"
        if not secret_file.exists():
            fd = os.open(secret_file, os.O_WRONLY | os.O_CREAT | os.O_EXCL, 0o600)
            with os.fdopen(fd, "w") as f:
                f.write(secrets.token_urlsafe(48))
        secret_file.chmod(0o600)
        secret = secret_file.read_text(encoding="utf-8").strip()
        if len(secret) < 32:
            raise ValueError(
                "Chave persistente inválida; não a substitua sem planejar a revogação das sessões."
            )
    return {
        "SECRET_KEY": secret,
        "DATABASE": str(data / "conversa.db"),
        "DEMO": False,
        "APP_NAME": settings.get("app_name", "Conversa"),
        "SESSION_COOKIE_SECURE": True,
        "SESSION_COOKIE_NAME": "conversa_session",
        "SERVER_MODE": True,
        "PUBLIC_URL": public_url.rstrip("/"),
        "INSTALL_TOKEN": install_token,
    }


def create_server_app(root=None, testing=False):
    from app import create_app

    config = load_server_config(root)
    if testing:
        config["TESTING"] = True
    return create_app(config)
