from __future__ import annotations

import json
from pathlib import Path
from uuid import uuid4

from fastapi import APIRouter, BackgroundTasks, File, HTTPException, UploadFile
from pydantic import BaseModel, Field

from app.db import fetch_all, fetch_one
from app.services.social_publish import PLATFORMS, get_configured_channels, run_publish_job

router = APIRouter(prefix="/api/marketing", tags=["marketing-api"])

BASE_DIR = Path(__file__).resolve().parent.parent.parent
UPLOAD_DIR = BASE_DIR / "static" / "uploads" / "marketing"


def _serialize_row(row: dict | None) -> dict | None:
    if not row:
        return None
    out = dict(row)
    for key, value in list(out.items()):
        if hasattr(value, "isoformat"):
            out[key] = value.isoformat()
    return out


def _serialize_rows(rows: list[dict]) -> list[dict]:
    return [_serialize_row(row) for row in rows]


class PublishRequest(BaseModel):
    text: str = Field(..., min_length=1, max_length=5000)
    image_url: str | None = None
    media_ids: list[int] = Field(default_factory=list)
    channels: list[str] = Field(default_factory=list)
    project_id: int | None = None


@router.post("/upload")
async def upload_marketing_media(file: UploadFile = File(...)) -> dict:
    data = await file.read()
    if not data:
        raise HTTPException(status_code=400, detail="empty file")
    UPLOAD_DIR.mkdir(parents=True, exist_ok=True)
    ext = Path(file.filename or "upload.bin").suffix or ".bin"
    filename = f"{uuid4().hex}{ext.lower()}"
    path = UPLOAD_DIR / filename
    path.write_bytes(data)
    media_url = f"/static/uploads/marketing/{filename}"

    row = fetch_one(
        """
        INSERT INTO marketing_media (filename, original_name, file_path, media_url, mime_type, size_bytes, created_at)
        VALUES (%s, %s, %s, %s, %s, %s, NOW())
        RETURNING id
        """,
        (
            filename,
            file.filename or filename,
            str(path),
            media_url,
            file.content_type or "application/octet-stream",
            len(data),
        ),
    )
    return {"media_id": row["id"], "url": media_url}


@router.post("/publish", status_code=202)
def create_publish_job(body: PublishRequest, background_tasks: BackgroundTasks) -> dict:
    channels = [c.strip().lower() for c in body.channels if c.strip()]
    invalid = [c for c in channels if c not in PLATFORMS]
    if invalid:
        raise HTTPException(status_code=400, detail=f"Unsupported channels: {', '.join(invalid)}")
    if not channels:
        channels = list(PLATFORMS)

    row = fetch_one(
        """
        INSERT INTO social_publish_jobs (text, image_url, media_ids, channels, status, created_at, updated_at)
        VALUES (%s, %s, %s::jsonb, %s::jsonb, %s, NOW(), NOW())
        RETURNING id
        """,
        (
            body.text,
            body.image_url,
            json.dumps(body.media_ids),
            json.dumps(channels),
            "queued",
        ),
    )
    job_id = int(row["id"])
    background_tasks.add_task(
        run_publish_job, job_id, body.text, channels, body.image_url, body.media_ids, body.project_id,
    )
    return {"job_id": job_id, "status": "queued", "channels": channels}


@router.get("/publish/{job_id}")
def get_publish_job(job_id: int) -> dict:
    row = fetch_one("SELECT * FROM social_publish_jobs WHERE id = %s", (job_id,))
    if not row:
        raise HTTPException(status_code=404, detail="Job not found")
    return {"job": _serialize_row(row)}


@router.get("/publish/history")
def list_publish_history(limit: int = 50) -> dict:
    safe_limit = max(1, min(limit, 200))
    rows = fetch_all(
        "SELECT * FROM social_publish_jobs ORDER BY created_at DESC LIMIT %s",
        (safe_limit,),
    )
    return {"items": _serialize_rows(rows), "count": len(rows)}


@router.get("/channels")
def list_channels() -> dict:
    items = get_configured_channels()
    return {"items": items, "platforms": list(PLATFORMS)}
