"""
Content Approval Gate
Ported & adapted từ BrightBean Studio apps/approvals/services.py
State machine: draft → pending_review → approved → scheduled → published
                                      → rejected / changes_requested

Canifa use case: AI generate outfit suggestion content
→ marketing review → approve → auto-schedule publish lên social media
"""

import json
import logging
import os
from datetime import datetime, timezone
from typing import Optional

from common.notification.engine import notify
from common.notification.events import EventType

logger = logging.getLogger(__name__)

CONTENT_FILE = os.path.join(
    os.path.dirname(os.path.abspath(__file__)), "..", "..", "data", "social_content.json"
)

# ─── Valid state transitions ─────────────────────────────────────────────────
TRANSITIONS = {
    "draft":              ["pending_review"],
    "pending_review":     ["approved", "rejected", "changes_requested"],
    "changes_requested":  ["pending_review", "draft"],
    "rejected":           ["draft"],
    "approved":           ["scheduled", "draft"],
    "scheduled":          ["published", "cancelled", "failed"],
    "published":          [],
    "cancelled":          [],
    "failed":             ["scheduled"],  # retry
}

STATUS_LABELS = {
    "draft":             "📝 Nháp",
    "pending_review":    "🔍 Chờ duyệt",
    "changes_requested": "✏️ Cần chỉnh sửa",
    "rejected":          "❌ Từ chối",
    "approved":          "✅ Đã duyệt",
    "scheduled":         "⏰ Đã lên lịch",
    "published":         "🚀 Đã đăng",
    "cancelled":         "🚫 Đã huỷ",
    "failed":            "💥 Thất bại",
}


# ─── Storage helpers ─────────────────────────────────────────────────────────

def _ensure_dir():
    os.makedirs(os.path.dirname(CONTENT_FILE), exist_ok=True)


def _load_contents() -> list[dict]:
    _ensure_dir()
    if not os.path.exists(CONTENT_FILE):
        return []
    try:
        with open(CONTENT_FILE, "r", encoding="utf-8") as f:
            return json.load(f)
    except Exception:
        return []


def _save_contents(data: list[dict]):
    _ensure_dir()
    with open(CONTENT_FILE, "w", encoding="utf-8") as f:
        json.dump(data, f, ensure_ascii=False, indent=2, default=str)


def _find_content(content_id: str) -> tuple[dict | None, int]:
    contents = _load_contents()
    for i, c in enumerate(contents):
        if c.get("id") == content_id:
            return c, i
    return None, -1


def _gen_id() -> str:
    import secrets
    return "cnt_" + secrets.token_hex(6)


# ─── Public API ──────────────────────────────────────────────────────────────

def create_content(
    title: str,
    caption: str,
    platforms: list[str],
    image_urls: list[str] | None = None,
    created_by: str = "ai_agent",
    tags: list[str] | None = None,
    metadata: dict | None = None,
) -> dict:
    """
    Tạo content mới (bắt đầu từ draft).
    Thường được gọi bởi AI stylist engine khi generate outfit suggestion.
    """
    content = {
        "id":         _gen_id(),
        "title":      title,
        "caption":    caption,
        "platforms":  platforms,        # ["facebook", "instagram", "tiktok"]
        "image_urls": image_urls or [],
        "tags":       tags or [],
        "status":     "draft",
        "created_by": created_by,
        "metadata":   metadata or {},
        "review_comment": "",
        "history":    [],
        "created_at": datetime.now(timezone.utc).isoformat(),
        "updated_at": datetime.now(timezone.utc).isoformat(),
    }

    contents = _load_contents()
    contents.insert(0, content)
    _save_contents(contents)

    logger.info("📝 Content created: %s", content["id"])
    return content


def _transition(content_id: str, new_status: str, comment: str = "", actor: str = "system") -> dict:
    """Internal: thực hiện state transition."""
    contents = _load_contents()
    content = None
    idx = -1
    for i, c in enumerate(contents):
        if c.get("id") == content_id:
            content = c
            idx = i
            break

    if content is None:
        raise ValueError(f"Content {content_id} not found")

    current = content["status"]
    allowed = TRANSITIONS.get(current, [])
    if new_status not in allowed:
        raise ValueError(f"Không thể chuyển từ '{current}' → '{new_status}'. Allowed: {allowed}")

    # Ghi lịch sử transition
    content.setdefault("history", []).append({
        "from": current,
        "to":   new_status,
        "comment": comment,
        "actor": actor,
        "at":  datetime.now(timezone.utc).isoformat(),
    })

    content["status"]       = new_status
    content["review_comment"] = comment
    content["updated_at"]   = datetime.now(timezone.utc).isoformat()
    contents[idx] = content
    _save_contents(contents)
    return content


def submit_for_review(content_id: str, submitted_by: str = "ai_agent") -> dict:
    """Submit content cho marketing review."""
    content = _transition(content_id, "pending_review", actor=submitted_by)
    notify(
        event_type=EventType.CONTENT_SUBMITTED,
        title=f"Content mới chờ duyệt: {content['title'][:50]}",
        body=f"AI đã tạo content và submit để review.\nPlatforms: {', '.join(content.get('platforms', []))}",
        data={"content_id": content_id, "platforms": content.get("platforms")},
    )
    return content


def approve_content(content_id: str, approved_by: str, comment: str = "") -> dict:
    """Marketing approve content — tiếp theo sẽ move vào queue scheduling."""
    content = _transition(content_id, "approved", comment=comment, actor=approved_by)
    notify(
        event_type=EventType.CONTENT_APPROVED,
        title=f"✅ Content đã được duyệt: {content['title'][:50]}",
        body=f"Duyệt bởi {approved_by}. {comment}",
        data={"content_id": content_id},
    )
    return content


def reject_content(content_id: str, rejected_by: str, comment: str) -> dict:
    """Marketing reject content — AI cần học từ lý do này."""
    if not comment.strip():
        raise ValueError("Phải có lý do khi từ chối content.")
    content = _transition(content_id, "rejected", comment=comment, actor=rejected_by)
    notify(
        event_type=EventType.CONTENT_REJECTED,
        title=f"❌ Content bị từ chối: {content['title'][:50]}",
        body=f"Từ chối bởi {rejected_by}.\nLý do: {comment}",
        data={"content_id": content_id, "reject_reason": comment},
    )
    # Feed rejection reason vào learning loop
    _feed_rejection_to_learning_loop(content, comment)
    return content


def request_changes(content_id: str, requested_by: str, comment: str) -> dict:
    """Marketing yêu cầu chỉnh sửa — không reject hoàn toàn."""
    if not comment.strip():
        raise ValueError("Phải mô tả cần chỉnh sửa gì.")
    content = _transition(content_id, "changes_requested", comment=comment, actor=requested_by)
    notify(
        event_type=EventType.CONTENT_CHANGES,
        title=f"✏️ Cần chỉnh sửa: {content['title'][:50]}",
        body=f"Yêu cầu bởi {requested_by}.\nCần sửa: {comment}",
        data={"content_id": content_id, "change_request": comment},
    )
    return content


def schedule_content(content_id: str, scheduled_at: str, actor: str = "system") -> dict:
    """Move approved content vào scheduled (đã có thời gian publish)."""
    content = _transition(content_id, "scheduled", actor=actor)
    contents = _load_contents()
    for c in contents:
        if c["id"] == content_id:
            c["scheduled_at"] = scheduled_at
            c["updated_at"]   = datetime.now(timezone.utc).isoformat()
    _save_contents(contents)
    return content


def mark_published(content_id: str, platform_results: dict | None = None) -> dict:
    """Mark content là đã publish thành công."""
    content = _transition(content_id, "published", actor="publisher")
    contents = _load_contents()
    for c in contents:
        if c["id"] == content_id:
            c["published_at"] = datetime.now(timezone.utc).isoformat()
            c["platform_results"] = platform_results or {}
    _save_contents(contents)
    notify(
        event_type=EventType.CONTENT_PUBLISHED,
        title=f"🚀 Đã đăng: {content['title'][:50]}",
        body=f"Content đã được publish lên {', '.join(content.get('platforms', []))}",
        data={"content_id": content_id},
    )
    return content


def mark_failed(content_id: str, error: str) -> dict:
    """Mark content là publish thất bại."""
    content = _transition(content_id, "failed", comment=error, actor="publisher")
    notify(
        event_type=EventType.CONTENT_FAILED,
        title=f"💥 Publish thất bại: {content['title'][:50]}",
        body=f"Lỗi: {error}",
        data={"content_id": content_id, "error": error},
    )
    return content


# ─── Queries ─────────────────────────────────────────────────────────────────

def list_contents(
    status: str | None = None,
    platform: str | None = None,
    limit: int = 50,
    offset: int = 0,
) -> dict:
    contents = _load_contents()
    if status:
        contents = [c for c in contents if c.get("status") == status]
    if platform:
        contents = [c for c in contents if platform in c.get("platforms", [])]
    total = len(contents)
    return {"total": total, "contents": contents[offset: offset + limit]}


def get_content(content_id: str) -> dict | None:
    content, _ = _find_content(content_id)
    return content


def get_approval_stats() -> dict:
    contents = _load_contents()
    stats: dict = {"total": len(contents), "by_status": {}}
    for c in contents:
        s = c.get("status", "unknown")
        stats["by_status"][s] = stats["by_status"].get(s, 0) + 1
    return stats


# ─── Learning loop integration ───────────────────────────────────────────────

def _feed_rejection_to_learning_loop(content: dict, reason: str):
    """Feed rejected content + reason vào Canifa feedback tracker → AI học."""
    try:
        from common.feedback_tracker import save_feedback
        save_feedback(
            trace_id=f"approval_reject_{content['id']}",
            rating=0,
            comment=f"[CONTENT REJECTED] {reason}",
            user_category="content_approval",
            ai_category="rejected_content",
            ai_severity="medium",
            ai_summary=(
                f"AI-generated content bị marketing reject.\n"
                f"Title: {content.get('title', '')}\n"
                f"Caption: {content.get('caption', '')[:200]}\n"
                f"Lý do reject: {reason}"
            ),
        )
        logger.info("🧠 Rejection fed to learning loop: %s", content["id"])
    except Exception as e:
        logger.error("Failed to feed rejection to learning loop: %s", e)
