"""Email relay VM122 → VM112 — status, config e teste (Spec 004 / Infra CODE)."""

from __future__ import annotations

import json
import os
import smtplib
from datetime import datetime, timezone
from email.message import EmailMessage
from pathlib import Path
from typing import Any

from app import mail_notify

CONFIG_PATH = Path(os.getenv("EMAIL_RELAY_CONFIG_PATH", "/data/email_relay_config.json"))
RELAY_HOST = os.getenv("DESK_RELAY_HOST", "10.10.10.112")
RELAY_PORT = int(os.getenv("DESK_RELAY_PORT", "25"))
SMTP_HOST = os.getenv("DESK_SMTP_HOST", "10.10.10.122")
SMTP_PORT = int(os.getenv("DESK_SMTP_PORT", "25"))
MAIL_FROM = os.getenv("DESK_MAIL_FROM", "ligbox-ops@ligbox.com.br")

DEFAULT_CONFIG: dict[str, Any] = {
    "vm": "122",
    "vm_label": "VM122 · Ops Desk",
    "service_id": "vm122-email-relay",
    "title": "Email Relay (Postfix)",
    "relayhost": RELAY_HOST,
    "relayport": RELAY_PORT,
    "smtp_host": SMTP_HOST,
    "smtp_port": SMTP_PORT,
    "mail_from": MAIL_FROM,
    "myorigin": "ligbox.com.br",
    "transport_local": {
        "ligbox.com.br": "LMTP [10.10.10.112]:7025",
        "ibytera.com": "LMTP [10.10.10.112]:7025",
        "dratcoin.com": "LMTP [10.10.10.112]:7025",
    },
    "external_route": "relayhost → mail.ligbox.com.br (DKIM/SPF)",
    "docs": "docs/postfix-vm122.md",
}


def _now() -> str:
    return datetime.now(timezone.utc).isoformat()


def load_config() -> dict[str, Any]:
    cfg = dict(DEFAULT_CONFIG)
    cfg["updated_at"] = _now()
    if CONFIG_PATH.is_file():
        try:
            stored = json.loads(CONFIG_PATH.read_text(encoding="utf-8"))
            if isinstance(stored, dict):
                cfg.update(stored)
        except Exception:
            pass
    return cfg


def save_config(patch: dict[str, Any]) -> dict[str, Any]:
    cfg = load_config()
    cfg.update(patch)
    cfg["updated_at"] = _now()
    CONFIG_PATH.parent.mkdir(parents=True, exist_ok=True)
    CONFIG_PATH.write_text(json.dumps(cfg, indent=2, ensure_ascii=False) + "\n", encoding="utf-8")
    return cfg


def _probe_smtp(host: str, port: int, timeout: float = 8.0) -> dict[str, Any]:
    try:
        with smtplib.SMTP(host, port, timeout=timeout) as smtp:
            code, _ = smtp.ehlo()
            smtp.noop()
        ok = 200 <= code < 400
        return {"ok": ok, "status": "online" if ok else "check", "detail": f"SMTP {host}:{port} EHLO {code}"}
    except Exception as exc:
        return {"ok": False, "status": "down", "detail": f"SMTP {host}:{port} — {exc}"}


def build_status() -> dict[str, Any]:
    cfg = load_config()
    local = _probe_smtp(cfg["smtp_host"], int(cfg["smtp_port"]))
    relay = _probe_smtp(cfg["relayhost"], int(cfg["relayport"]))
    ok = bool(local.get("ok") and relay.get("ok"))
    detail_parts = [
        local.get("detail", ""),
        f"relay {cfg['relayhost']}:{cfg['relayport']} — {relay.get('detail', '')}",
    ]
    return {
        "ok": ok,
        "status": "online" if ok else ("check" if local.get("ok") else "down"),
        "detail": " · ".join(p for p in detail_parts if p),
        "config": cfg,
        "checks": {
            "smtp_local": local,
            "smtp_relay": relay,
        },
        "generated_at": _now(),
    }


def probe_stack() -> dict[str, Any]:
    st = build_status()
    return {"ok": st["ok"], "status": st["status"], "detail": st["detail"]}


def send_test_email(to: str, subject: str | None = None) -> dict[str, Any]:
    to = (to or "").strip()
    if not to:
        return {"ok": False, "detail": "destinatário vazio"}
    subj = subject or "[Ligbox Ops] Teste Email Relay VM122"
    body = (
        "Teste do relay Postfix VM122 → VM112 (mail.ligbox.com.br).\n\n"
        f"Gerado em: {_now()}\n"
    )
    ok = mail_notify.send_email(to, subj, body)
    return {
        "ok": ok,
        "detail": "enviado via SMTP local" if ok else "falha SMTP — verificar Postfix/relay",
        "to": to,
        "from": MAIL_FROM,
        "at": _now(),
    }
