"""Operational feed mock store. Spec 041 · OF-API-001."""

from __future__ import annotations

import json
import sqlite3
from datetime import datetime, timezone, timedelta
from typing import Any

CHANNELS = (
    ("all", "Todos os canais"),
    ("email", "Email"),
    ("whatsapp", "WhatsApp API"),
    ("voice", "Telefonia / Voz"),
    ("sms", "SMS"),
    ("telegram", "Telegram"),
    ("tickets", "Tickets"),
    ("agents", "Agentes IA"),
    ("internal", "Solicitações internas"),
    ("clients", "Clientes"),
    ("alerts", "Alertas sistema"),
)

PRIORITIES = ("normal", "high", "critical")


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


def _minutes_ago(minutes: int) -> str:
    return (datetime.now(timezone.utc) - timedelta(minutes=minutes)).isoformat()


def init_inbox_schema(conn: sqlite3.Connection) -> None:
    conn.executescript(
        """
        CREATE TABLE IF NOT EXISTS ops_inbox_events (
            id TEXT PRIMARY KEY,
            channel TEXT NOT NULL,
            event_type TEXT NOT NULL,
            priority TEXT NOT NULL DEFAULT 'normal',
            title TEXT NOT NULL,
            preview TEXT NOT NULL,
            tags_json TEXT NOT NULL DEFAULT '[]',
            assignee TEXT,
            status TEXT NOT NULL DEFAULT 'open',
            contact_name TEXT,
            contact_company TEXT,
            contact_cnpj TEXT,
            contact_client_id TEXT,
            sla_minutes INTEGER NOT NULL DEFAULT 60,
            sla_remaining_sec INTEGER NOT NULL DEFAULT 3600,
            created_at TEXT NOT NULL,
            updated_at TEXT NOT NULL
        );
        CREATE TABLE IF NOT EXISTS ops_inbox_messages (
            id INTEGER PRIMARY KEY AUTOINCREMENT,
            event_id TEXT NOT NULL,
            author_type TEXT NOT NULL,
            author_label TEXT NOT NULL,
            body TEXT NOT NULL,
            created_at TEXT NOT NULL,
            FOREIGN KEY (event_id) REFERENCES ops_inbox_events(id)
        );
        CREATE INDEX IF NOT EXISTS idx_ops_inbox_events_channel ON ops_inbox_events(channel);
        CREATE INDEX IF NOT EXISTS idx_ops_inbox_events_status ON ops_inbox_events(status);
        """
    )
    count = conn.execute("SELECT COUNT(*) c FROM ops_inbox_events").fetchone()["c"]
    if count == 0:
        _seed_inbox(conn)


def _seed_inbox(conn: sqlite3.Connection) -> None:
    now = _now()
    seeds = [
        {
            "id": "evt-wa-001",
            "channel": "whatsapp",
            "event_type": "message",
            "priority": "high",
            "title": "Cliente: Empresa Alpha — Não consigo acessar o painel financeiro",
            "preview": "Bom dia, após o login aparece erro 403 no módulo billing…",
            "tags": ["Cliente", "Acesso", "Infraestrutura"],
            "assignee": "Editor",
            "status": "open",
            "contact_name": "Empresa Alpha",
            "contact_company": "Empresa Alpha Ltda",
            "contact_cnpj": "12.345.678/0001-90",
            "contact_client_id": "CLI-8842",
            "sla_minutes": 15,
            "sla_remaining_sec": 750,
            "created_at": _minutes_ago(2),
        },
        {
            "id": "evt-int-002",
            "channel": "internal",
            "event_type": "request",
            "priority": "normal",
            "title": "Carlos — Financeiro: Aprovar reembolso #8821",
            "preview": "Solicitação interna aguardando aprovação do Chefe Ops",
            "tags": ["Interno", "Financeiro"],
            "assignee": "Super Admin",
            "status": "pending",
            "contact_name": "Carlos Mendes",
            "contact_company": "Ligbox Ops",
            "contact_cnpj": "",
            "contact_client_id": "",
            "sla_minutes": 120,
            "sla_remaining_sec": 5400,
            "created_at": _minutes_ago(18),
        },
        {
            "id": "evt-ai-003",
            "channel": "agents",
            "event_type": "alert",
            "priority": "critical",
            "title": "Agente A3 — CPU VM122 acima de 92%",
            "preview": "Alerta automático: load average 4.2 — recomendação de escala",
            "tags": ["Agente IA", "Infra", "VM122"],
            "assignee": "AI Agent",
            "status": "open",
            "contact_name": "Watchman A3",
            "contact_company": "Ligbox Platform",
            "contact_cnpj": "",
            "contact_client_id": "",
            "sla_minutes": 30,
            "sla_remaining_sec": 1200,
            "created_at": _minutes_ago(5),
        },
        {
            "id": "evt-em-004",
            "channel": "email",
            "event_type": "message",
            "priority": "normal",
            "title": "Empresa Beta — Pedido de upgrade de plano",
            "preview": "Gostaríamos de migrar para o plano enterprise…",
            "tags": ["Cliente", "Comercial"],
            "assignee": "Sales Admin",
            "status": "open",
            "contact_name": "Empresa Beta",
            "contact_company": "Beta Serviços SA",
            "contact_cnpj": "98.765.432/0001-10",
            "contact_client_id": "CLI-1201",
            "sla_minutes": 240,
            "sla_remaining_sec": 12000,
            "created_at": _minutes_ago(45),
        },
        {
            "id": "evt-tk-005",
            "channel": "tickets",
            "event_type": "ticket",
            "priority": "high",
            "title": "Ticket #4412 — Erro importação DNS",
            "preview": "Falha ao sincronizar zona dns.example.com",
            "tags": ["Ticket", "DNS"],
            "assignee": "NOC",
            "status": "open",
            "contact_name": "Suporte N1",
            "contact_company": "Cliente Gamma",
            "contact_cnpj": "",
            "contact_client_id": "CLI-3300",
            "sla_minutes": 60,
            "sla_remaining_sec": 2100,
            "created_at": _minutes_ago(12),
        },
        {
            "id": "evt-vc-006",
            "channel": "voice",
            "event_type": "missed_call",
            "priority": "normal",
            "title": "Chamada perdida — +55 11 98765-4321",
            "preview": "Duração 0s · fila comercial",
            "tags": ["Telefonia"],
            "assignee": None,
            "status": "open",
            "contact_name": "Desconhecido",
            "contact_company": "",
            "contact_cnpj": "",
            "contact_client_id": "",
            "sla_minutes": 30,
            "sla_remaining_sec": 900,
            "created_at": _minutes_ago(8),
        },
    ]
    for s in seeds:
        conn.execute(
            """
            INSERT INTO ops_inbox_events
            (id, channel, event_type, priority, title, preview, tags_json, assignee, status,
             contact_name, contact_company, contact_cnpj, contact_client_id,
             sla_minutes, sla_remaining_sec, created_at, updated_at)
            VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
            """,
            (
                s["id"], s["channel"], s["event_type"], s["priority"], s["title"], s["preview"],
                json.dumps(s["tags"]), s["assignee"], s["status"],
                s["contact_name"], s["contact_company"], s["contact_cnpj"], s["contact_client_id"],
                s["sla_minutes"], s["sla_remaining_sec"], s["created_at"], s["created_at"],
            ),
        )
    msgs = [
        ("evt-wa-001", "user", "Empresa Alpha", "Bom dia, não consigo acessar o painel financeiro."),
        ("evt-wa-001", "agent", "AI Agent", "Detectei erro 403 no módulo billing. Encaminhei para suporte."),
        ("evt-wa-001", "system", "Sistema", "SLA iniciado — 15 min"),
    ]
    for event_id, author_type, author_label, body in msgs:
        conn.execute(
            """
            INSERT INTO ops_inbox_messages (event_id, author_type, author_label, body, created_at)
            VALUES (?, ?, ?, ?, ?)
            """,
            (event_id, author_type, author_label, body, now),
        )


def inbox_stats(conn: sqlite3.Connection) -> dict:
    total = conn.execute("SELECT COUNT(*) c FROM ops_inbox_events").fetchone()["c"]
    pending = conn.execute(
        "SELECT COUNT(*) c FROM ops_inbox_events WHERE status IN ('open','pending')"
    ).fetchone()["c"]
    critical = conn.execute(
        "SELECT COUNT(*) c FROM ops_inbox_events WHERE priority = 'critical'"
    ).fetchone()["c"]
    channels = []
    for cid, label in CHANNELS:
        if cid == "all":
            cnt = total
        else:
            cnt = conn.execute(
                "SELECT COUNT(*) c FROM ops_inbox_events WHERE channel = ?",
                (cid,),
            ).fetchone()["c"]
        channels.append({"id": cid, "label": label, "count": cnt})
    return {
        "events_today": total,
        "pending": pending,
        "critical": critical,
        "awaiting_you": conn.execute(
            "SELECT COUNT(*) c FROM ops_inbox_events WHERE assignee IS NOT NULL AND status = 'open'"
        ).fetchone()["c"],
        "sla_avg_pct": 96,
        "channels": channels,
    }


def list_events(
    conn: sqlite3.Connection,
    *,
    channel: str | None = None,
    priority: str | None = None,
    status: str | None = None,
    q: str | None = None,
    limit: int = 128,
) -> list[dict]:
    sql = "SELECT * FROM ops_inbox_events WHERE 1=1"
    params: list[Any] = []
    if channel and channel != "all":
        sql += " AND channel = ?"
        params.append(channel)
    if priority:
        sql += " AND priority = ?"
        params.append(priority)
    if status:
        sql += " AND status = ?"
        params.append(status)
    if q:
        sql += " AND (title LIKE ? OR preview LIKE ? OR contact_name LIKE ?)"
        like = f"%{q}%"
        params.extend([like, like, like])
    sql += " ORDER BY datetime(created_at) DESC LIMIT ?"
    params.append(limit)
    rows = conn.execute(sql, params).fetchall()
    out = []
    for row in rows:
        item = dict(row)
        try:
            item["tags"] = json.loads(item.pop("tags_json") or "[]")
        except json.JSONDecodeError:
            item["tags"] = []
        out.append(item)
    return out


def get_event(conn: sqlite3.Connection, event_id: str) -> dict | None:
    row = conn.execute("SELECT * FROM ops_inbox_events WHERE id = ?", (event_id,)).fetchone()
    if not row:
        return None
    item = dict(row)
    item["tags"] = json.loads(item.pop("tags_json") or "[]")
    msgs = conn.execute(
        """
        SELECT id, author_type, author_label, body, created_at
        FROM ops_inbox_messages WHERE event_id = ? ORDER BY id ASC
        """,
        (event_id,),
    ).fetchall()
    item["messages"] = [dict(m) for m in msgs]
    return item


def add_message(conn: sqlite3.Connection, event_id: str, author_type: str, author_label: str, body: str) -> dict:
    now = _now()
    cur = conn.execute(
        """
        INSERT INTO ops_inbox_messages (event_id, author_type, author_label, body, created_at)
        VALUES (?, ?, ?, ?, ?)
        """,
        (event_id, author_type, author_label, body.strip(), now),
    )
    conn.execute(
        "UPDATE ops_inbox_events SET updated_at = ? WHERE id = ?",
        (now, event_id),
    )
    return {"id": cur.lastrowid, "event_id": event_id, "author_type": author_type,
            "author_label": author_label, "body": body.strip(), "created_at": now}


def patch_event(conn: sqlite3.Connection, event_id: str, **fields: Any) -> dict | None:
    allowed = {"status", "assignee", "priority"}
    updates = []
    params: list[Any] = []
    for k, v in fields.items():
        if k in allowed and v is not None:
            updates.append(f"{k} = ?")
            params.append(v)
    if not updates:
        ev = get_event(conn, event_id)
        return ev
    updates.append("updated_at = ?")
    params.append(_now())
    params.append(event_id)
    conn.execute(
        f"UPDATE ops_inbox_events SET {', '.join(updates)} WHERE id = ?",
        params,
    )
    return get_event(conn, event_id)
