"""Motor de marketing automático JobsWorld: genera, programa y ejecuta campañas."""

from __future__ import annotations

import json
import secrets
from datetime import datetime, timezone
from pathlib import Path
from typing import Any

from app.core.config import get_settings
from app.services import brand, campaigns, proposals
from app.services import ai_cv


def _log_path() -> Path:
    p = get_settings().data_dir / "marketing-automation.log.jsonl"
    p.parent.mkdir(parents=True, exist_ok=True)
    return p


def _append_log(event: str, detail: dict[str, Any]) -> None:
    row = {
        "at": datetime.now(timezone.utc).isoformat(),
        "event": event,
        **detail,
    }
    with _log_path().open("a", encoding="utf-8") as f:
        f.write(json.dumps(row, ensure_ascii=False) + "\n")


def status() -> dict[str, Any]:
    items = campaigns.list_campaigns()
    by = {}
    for c in items:
        st = c.get("status") or "draft"
        by[st] = by.get(st, 0) + 1
    return {
        "brand": brand.get_active().get("name"),
        "campaigns_total": len(items),
        "by_status": by,
        "pending_proposals": len(proposals.list_proposals("proposed")),
        "auto_enabled": True,
    }


def generate_week_pack(*, use_llm: bool = True) -> dict[str, Any]:
    """Genera 7 piezas de contenido (cola ready) + propuestas Bridge opcionales."""
    active = brand.get_active()
    created_camps: list[dict[str, Any]] = []
    days = [
        ("linkedin", "D1 — Problema pestañas de empleo", "CTA free + UTM week_auto_d1"),
        ("linkedin", "D2 — Demo CV con revisión humana", "CTA /cv + UTM week_auto_d2"),
        ("linkedin", "D3 — Precio vs Teal/Huntr", "CTA /pricing Profesional + UTM week_auto_d3"),
        ("telegram", "D4 — Privacidad IA local", "CTA waitlist + UTM week_auto_d4"),
        ("linkedin", "D5 — Insight salarial lead magnet", "CTA /weekly-index + UTM week_auto_d5"),
        ("linkedin", "D6 — Referral challenge", "CTA /invite referral + UTM week_auto_d6"),
        ("linkedin", "D7 — Early adopter Carrera Max", "CTA /pricing Max + UTM week_auto_d7"),
    ]

    bodies: list[str] = []
    if use_llm:
        system = (
            "Eres growth marketer de un portal de empleo ES+INT. "
            "Devuelve SOLO JSON array de 7 strings (posts cortos en español), sin markdown."
        )
        user = (
            f"Marca: {active.get('name')}. Tagline: {active.get('tagline')}. "
            "Planes: Free / Esencial 7,90€ / Profesional 14,90€ (héroe) / Max 24,90€. "
            "Diferenciadores: España-first, IA local, CV con gate humano. "
            "7 posts para una semana de lanzamiento (hooks + CTA)."
        )
        try:
            raw = ai_cv._chat(system, user)  # type: ignore[attr-defined]
            text = raw.strip()
            if text.startswith("```"):
                text = text.strip("`")
                if text.lower().startswith("json"):
                    text = text[4:].strip()
            start, end = text.find("["), text.rfind("]")
            if start >= 0 and end > start:
                arr = json.loads(text[start : end + 1])
                if isinstance(arr, list):
                    bodies = [str(x).strip() for x in arr if str(x).strip()][:7]
        except Exception:  # noqa: BLE001
            bodies = []

    if len(bodies) < 7:
        bodies = [
            f"{active.get('name')}: deja de saltar entre 15 portales. Feed ES+INT + CV con revisión. Empieza gratis → /pricing",
            f"Adapta tu CV a la oferta con IA local y aprueba tú antes de enviar. {active.get('tagline')}",
            "Teal/Huntr ~30–40€. Profesional JobsWorld ~15€. Mismo problema, precio de volumen.",
            "Tu CV no viaja a un SaaS USA: Ollama en lab privado + revisión humana.",
            "Lead magnet: índice salarial semanal ES. Entra gratis y mide tu mercado.",
            "Invita 3 colegas → mes Profesional. Referral en /invite.",
            "Early adopter: potencia Max a precio irrechazable. /pricing",
        ]

    for i, ((channel, title, _), body) in enumerate(zip(days, bodies)):
        camp = campaigns.create_campaign(
            title=title,
            channel=channel,
            body=body,
            utm_campaign=f"week_auto_d{i+1}_{secrets.token_hex(2)}",
            status="ready",
        )
        created_camps.append(camp)

    props = proposals.generate_from_lab(use_llm=use_llm, count=3)
    _append_log(
        "generate_week_pack",
        {"campaigns": len(created_camps), "proposals": len(props)},
    )
    return {
        "ok": True,
        "campaigns": created_camps,
        "proposals": props,
        "brand": active.get("name"),
    }


def advance_ready_campaigns(limit: int = 2) -> dict[str, Any]:
    """Marca hasta N campañas 'ready' como 'sent' (export/cola manual — no publica en redes)."""
    moved = []
    for c in campaigns.list_campaigns():
        if c.get("status") != "ready":
            continue
        updated = campaigns.update_campaign(c["id"], status="sent")
        moved.append(updated)
        _append_log("campaign_sent", {"id": c["id"], "channel": c.get("channel")})
        if len(moved) >= limit:
            break
    return {"ok": True, "sent": moved, "count": len(moved)}


def auto_tick() -> dict[str, Any]:
    """Tick periódico: si no hay ready, genera pack; si hay, publica 1."""
    ready = [c for c in campaigns.list_campaigns() if c.get("status") == "ready"]
    if not ready:
        pack = generate_week_pack(use_llm=True)
        return {"action": "generated", **pack}
    sent = advance_ready_campaigns(limit=1)
    return {"action": "marked_sent", "note": "No publica en redes; marca ready→sent para tracking", **sent}
