from __future__ import annotations

import json
import random
from dataclasses import asdict, dataclass
from datetime import date, datetime
from pathlib import Path

# --- Layouts (must match VisualRenderer methods where applicable) ---
LAYOUTS = (
    "magazine_cover",
    "editorial_overlay",
    "apple_keynote",
    "pitch_deck",
    "bento_grid",
    "hero_banner",
    "infographic",
    "news_broadcast",
    "timeline",
    "dashboard_ui",
    "split_comparison",
    "glass_card",
    "minimal_premium",
    "neon_tech",
    "bold_stat",
    "gradient_story",
    "corporate_linkedin",
    "cyberpunk",
)

TYPOGRAPHY = (
    "modern_startup",
    "apple_minimal",
    "swiss",
    "luxury",
    "brutalist",
    "newspaper",
    "futuristic",
    "editorial",
)

BACKGROUNDS = (
    "glassmorphism",
    "gradient_mesh",
    "3d_environment",
    "minimal_white",
    "dark_premium",
    "tech_grid",
    "abstract_geometry",
    "neural_network",
    "liquid_gradient",
    "aurora",
    "cyberpunk_city",
    "paper_texture",
    "noise_texture",
    "mesh_gradient",
)

VIDEO_STYLES = (
    "cinematic",
    "kinetic",
    "glitch",
    "parallax",
    "broadcast",
    "product_reveal",
    "data_motion",
)

ILLUSTRATION_STYLES = (
    "editorial_3d",
    "apple_product",
    "stripe_fintech",
    "nvidia_compute",
    "openai_research",
    "figma_ui",
    "linear_saas",
    "arc_browser",
    "cyber_noir",
    "photoreal_tech",
)

# 30+ premium palettes (name + hex colors)
PALETTES: list[dict] = [
    {"name": "electric_monday", "colors": ["#0A1628", "#00D4FF", "#FFFFFF", "#5B8CFF"]},
    {"name": "neon_tuesday", "colors": ["#0D0221", "#C77DFF", "#FF2E97", "#1A0A3E"]},
    {"name": "ember_wednesday", "colors": ["#0C0C0C", "#FF6B00", "#D4AF37", "#2A2A2A"]},
    {"name": "emerald_thursday", "colors": ["#042F2E", "#10B981", "#FFFFFF", "#14B8A6"]},
    {"name": "crimson_friday", "colors": ["#1A0505", "#EF4444", "#374151", "#F8FAFC"]},
    {"name": "aurora_saturday", "colors": ["#0F0A1F", "#A78BFA", "#38BDF8", "#F472B6"]},
    {"name": "minimal_sunday", "colors": ["#FAF7F2", "#E8E0D5", "#2C2C2C", "#8B7355"]},
    {"name": "stripe_violet", "colors": ["#0A2540", "#635BFF", "#00D4FF", "#F6F9FC"]},
    {"name": "linear_indigo", "colors": ["#0D0D12", "#5E6AD2", "#FFFFFF", "#8B8BA7"]},
    {"name": "figma_sunset", "colors": ["#1E1E1E", "#A259FF", "#F24E1E", "#FF7262"]},
    {"name": "nvidia_green", "colors": ["#000000", "#76B900", "#FFFFFF", "#1A1A1A"]},
    {"name": "apple_silver", "colors": ["#F5F5F7", "#1D1D1F", "#86868B", "#0071E3"]},
    {"name": "openai_teal", "colors": ["#0D0D0D", "#10A37F", "#FFFFFF", "#1A1A1A"]},
    {"name": "arc_space", "colors": ["#1C1C1E", "#FF6B6B", "#4ECDC4", "#FFE66D"]},
    {"name": "framer_blue", "colors": ["#000000", "#0099FF", "#FFFFFF", "#333333"]},
    {"name": "gold_luxury", "colors": ["#0A0A0A", "#C9A227", "#F5E6C8", "#2D2D2D"]},
    {"name": "graphite_orange", "colors": ["#1C1917", "#F97316", "#FAFAF9", "#44403C"]},
    {"name": "beige_charcoal", "colors": ["#F5F0E8", "#2D2A26", "#A89F91", "#8B4513"]},
    {"name": "cyan_ice", "colors": ["#F0FDFF", "#0891B2", "#164E63", "#22D3EE"]},
    {"name": "magenta_void", "colors": ["#0B0014", "#FF00AA", "#7C3AED", "#E0E7FF"]},
    {"name": "forest_mist", "colors": ["#052E16", "#4ADE80", "#ECFDF5", "#166534"]},
    {"name": "ocean_depth", "colors": ["#020617", "#0EA5E9", "#38BDF8", "#F0F9FF"]},
    {"name": "lava_night", "colors": ["#18080A", "#FB7185", "#FBBF24", "#451A1A"]},
    {"name": "mint_mono", "colors": ["#FFFFFF", "#0F766E", "#99F6E4", "#134E4A"]},
    {"name": "paper_ink", "colors": ["#FFFEF7", "#111111", "#DC2626", "#6B7280"]},
    {"name": "holo_mesh", "colors": ["#111827", "#EC4899", "#8B5CF6", "#06B6D4"]},
    {"name": "steel_blue", "colors": ["#0F172A", "#64748B", "#94A3B8", "#E2E8F0"]},
    {"name": "sakura_night", "colors": ["#1A0A14", "#FB7185", "#FCE7F3", "#9D174D"]},
    {"name": "matrix_green", "colors": ["#020202", "#00FF41", "#003B00", "#39FF14"]},
    {"name": "copper_dark", "colors": ["#1C1410", "#B87333", "#E8D5C4", "#3D2914"]},
    {"name": "ice_lilac", "colors": ["#F8F7FF", "#7C3AED", "#C4B5FD", "#1E1B4B"]},
    {"name": "sunset_deck", "colors": ["#1A0F0A", "#FF8A00", "#FF3D00", "#FFF3E0"]},
]

WEEKDAY_PALETTE_INDEX = {
    0: 0,   # Monday electric
    1: 1,   # Tuesday neon
    2: 2,   # Wednesday ember
    3: 3,   # Thursday emerald
    4: 4,   # Friday crimson
    5: 5,   # Saturday aurora
    6: 6,   # Sunday minimal
}


@dataclass
class CreativeBrief:
    layout: str
    typography: str
    background: str
    palette_name: str
    palette: list[str]
    illustration_style: str
    video_style: str
    aspect: str  # square | portrait


class CreativeDirector:
    """Assigns unique creative directions and persists history to avoid repeats."""

    def __init__(self, history_path: Path):
        self.history_path = history_path
        self.history_path.parent.mkdir(parents=True, exist_ok=True)
        self.history = self._load()

    def _load(self) -> dict:
        if self.history_path.exists():
            try:
                return json.loads(self.history_path.read_text(encoding="utf-8"))
            except Exception:
                pass
        return {"posts": [], "last_palette": None, "last_layout": None, "last_date_palette": None}

    def save(self) -> None:
        self.history_path.write_text(json.dumps(self.history, indent=2), encoding="utf-8")

    def assign_batch(self, batch_size: int) -> list[CreativeBrief]:
        briefs: list[CreativeBrief] = []
        used_layouts: set[str] = set()
        used_palettes: set[str] = set()
        last_layout = self.history.get("last_layout")
        last_palette = self.history.get("last_palette")

        # Daily theme preference
        today = date.today()
        day_palette = PALETTES[WEEKDAY_PALETTE_INDEX[today.weekday()]]
        if self.history.get("last_date_palette") == today.isoformat():
            # Already used weekday default today — randomize
            day_palette = None

        for i in range(batch_size):
            layout = self._pick(LAYOUTS, exclude={last_layout, *used_layouts} if last_layout else used_layouts)
            typo = random.choice(TYPOGRAPHY)
            bg = random.choice(BACKGROUNDS)
            illust = random.choice(ILLUSTRATION_STYLES)
            video = random.choice(VIDEO_STYLES)
            aspect = random.choice(["square", "portrait"] if i % 2 else ["square", "square", "portrait"])

            if i == 0 and day_palette and day_palette["name"] != last_palette:
                pal = day_palette
            else:
                candidates = [p for p in PALETTES if p["name"] not in used_palettes and p["name"] != last_palette]
                if not candidates:
                    candidates = PALETTES
                pal = random.choice(candidates)

            brief = CreativeBrief(
                layout=layout,
                typography=typo,
                background=bg,
                palette_name=pal["name"],
                palette=list(pal["colors"]),
                illustration_style=illust,
                video_style=video,
                aspect=aspect,
            )
            briefs.append(brief)
            used_layouts.add(layout)
            used_palettes.add(pal["name"])
            last_layout = layout
            last_palette = pal["name"]

        return briefs

    def record(self, briefs: list[CreativeBrief]) -> None:
        for b in briefs:
            self.history.setdefault("posts", []).append(
                {**asdict(b), "at": datetime.now().isoformat(timespec="seconds")}
            )
        self.history["posts"] = self.history["posts"][-80:]
        if briefs:
            self.history["last_layout"] = briefs[-1].layout
            self.history["last_palette"] = briefs[-1].palette_name
            self.history["last_date_palette"] = date.today().isoformat()
        self.save()

    def recent_summary(self, n: int = 8) -> str:
        posts = self.history.get("posts") or []
        recent = posts[-n:]
        if not recent:
            return "(no prior posts — full creative freedom)"
        lines = []
        for p in recent:
            lines.append(
                f"- layout={p.get('layout')} palette={p.get('palette_name')} "
                f"type={p.get('typography')} bg={p.get('background')} style={p.get('illustration_style')}"
            )
        return "\n".join(lines)

    @staticmethod
    def _pick(options: tuple[str, ...], exclude: set) -> str:
        pool = [o for o in options if o not in exclude]
        return random.choice(pool or list(options))

    def as_prompt_block(self, briefs: list[CreativeBrief]) -> str:
        lines = []
        for i, b in enumerate(briefs, 1):
            lines.append(
                f"idea-{i:02d} MUST use:\n"
                f"  layout: {b.layout}\n"
                f"  typography: {b.typography}\n"
                f"  background: {b.background}\n"
                f"  palette_name: {b.palette_name}\n"
                f"  palette: {b.palette}\n"
                f"  illustration_style: {b.illustration_style}\n"
                f"  video_style: {b.video_style}\n"
                f"  aspect: {b.aspect}"
            )
        return "\n\n".join(lines)
