"""
Content Generator
=================
Generated by El Gringo team (grok-coder won consensus).
Fixed: uses ask() instead of nonexistent generate_content(), proper async handling,
lazy orchestrator init, content queue with file-based persistence.
"""

import asyncio
import json
import logging
import uuid
from datetime import datetime
from pathlib import Path
from threading import Lock
from typing import Dict, List, Optional

logger = logging.getLogger(__name__)

BASE_DIR = Path.home() / ".ai-dev-team" / "workflow" / "content"
QUEUE_FILE = BASE_DIR.parent / "content_queue.json"
BASE_DIR.mkdir(parents=True, exist_ok=True)


class ContentGenerator:
    def __init__(self):
        self._team = None
        self._lock = Lock()

    def _get_team(self):
        if self._team is None:
            from elgringo.orchestrator import AIDevTeam
            self._team = AIDevTeam()
        return self._team

    def _generate(self, prompt: str, system_context: str = "") -> str:
        team = self._get_team()
        full_prompt = f"{system_context}\n\n{prompt}" if system_context else prompt
        try:
            try:
                loop = asyncio.get_running_loop()
            except RuntimeError:
                loop = None

            if loop is not None and loop.is_running():
                # Running inside an async context (e.g. Gradio) — use a new thread
                import concurrent.futures
                def _in_new_loop():
                    new_loop = asyncio.new_event_loop()
                    asyncio.set_event_loop(new_loop)
                    try:
                        return new_loop.run_until_complete(team.ask(full_prompt))
                    finally:
                        new_loop.close()
                with concurrent.futures.ThreadPoolExecutor() as pool:
                    result = pool.submit(_in_new_loop).result()
            else:
                # No running loop (bare thread or main thread) — safe to asyncio.run()
                result = asyncio.run(team.ask(full_prompt))
            if isinstance(result, str):
                return result
            # AgentResponse has a .content attribute with the actual text
            return getattr(result, "content", str(result))
        except Exception as e:
            logger.error(f"Content generation failed: {e}")
            return ""

    def _save(self, content_type: str, data: Dict) -> str:
        item_id = str(uuid.uuid4())[:8]
        item = {
            "id": item_id,
            "type": content_type,
            "data": data,
            "status": "draft",
            "created_at": datetime.now().isoformat(),
        }
        path = BASE_DIR / f"{item_id}.json"
        with self._lock:
            with path.open("w") as f:
                json.dump(item, f, indent=2)
        return item_id

    def generate_linkedin_post(self, topic: str, tone: str = "professional",
                               context: str = "") -> Dict:
        prompt = (
            f"Write a LinkedIn post about: {topic}\n"
            f"Tone: {tone}\n"
            f"Context: {context}\n\n"
            "Output JSON with these exact keys:\n"
            '{"title": "...", "hook": "first line that grabs attention", '
            '"body": "main content 150-300 words", "cta": "call to action", '
            '"hashtags": ["#tag1", "#tag2"], "suggested_publish_time": "Tuesday 9am"}'
        )
        raw = self._generate(prompt, "You are a professional LinkedIn content creator.")
        data = self._try_parse_json(raw, {
            "title": topic, "hook": "", "body": raw, "cta": "",
            "hashtags": [], "suggested_publish_time": "",
        })
        data["_item_id"] = self._save("linkedin_post", data)
        return data

    def generate_blog_post(self, topic: str, audience: str,
                           key_points: Optional[List[str]] = None) -> Dict:
        points = ", ".join(key_points) if key_points else "cover the key aspects"
        prompt = (
            f"Write a blog post about: {topic}\n"
            f"Target audience: {audience}\n"
            f"Key points to cover: {points}\n\n"
            "Output JSON: {\"title\": \"\", \"meta_description\": \"\", "
            "\"sections\": [{\"heading\": \"\", \"content\": \"\"}], "
            "\"cta\": \"\", \"tags\": []}"
        )
        raw = self._generate(prompt, "You are an expert technical blog writer.")
        data = self._try_parse_json(raw, {
            "title": topic, "meta_description": "", "sections": [{"heading": topic, "content": raw}],
            "cta": "", "tags": [],
        })
        data["_item_id"] = self._save("blog_post", data)
        return data

    def generate_newsletter(self, topic: str, highlights: Optional[List[str]] = None,
                            metrics: Optional[Dict] = None) -> Dict:
        prompt = (
            f"Write an email newsletter about: {topic}\n"
            f"Highlights: {highlights or []}\n"
            f"Metrics to mention: {metrics or {}}\n\n"
            "Output JSON: {\"subject\": \"\", \"preview_text\": \"\", "
            "\"sections\": [{\"heading\": \"\", \"content\": \"\"}], \"cta\": \"\"}"
        )
        raw = self._generate(prompt, "You are a SaaS email newsletter writer.")
        data = self._try_parse_json(raw, {
            "subject": topic, "preview_text": "", "sections": [], "cta": "",
        })
        data["_item_id"] = self._save("newsletter", data)
        return data

    def generate_release_notes(self, commits: Optional[List[str]] = None,
                               sprint_data: Optional[Dict] = None) -> Dict:
        prompt = (
            f"Write release notes.\n"
            f"Recent commits: {commits or []}\n"
            f"Sprint data: {sprint_data or {}}\n\n"
            "Output JSON: {\"version\": \"\", \"date\": \"\", "
            "\"features\": [], \"fixes\": [], \"breaking_changes\": []}"
        )
        raw = self._generate(prompt, "You are a developer relations writer.")
        data = self._try_parse_json(raw, {
            "version": "", "date": datetime.now().strftime("%Y-%m-%d"),
            "features": [], "fixes": [], "breaking_changes": [],
        })
        data["_item_id"] = self._save("release_notes", data)
        return data

    @staticmethod
    def _try_parse_json(text: str, fallback: Dict) -> Dict:
        import re
        match = re.search(r"\{[\s\S]*\}", text)
        if match:
            try:
                return json.loads(match.group())
            except json.JSONDecodeError:
                pass
        return fallback


class ContentQueue:
    def __init__(self):
        self._lock = Lock()
        if not QUEUE_FILE.exists():
            QUEUE_FILE.write_text("[]")

    def _load(self) -> List[Dict]:
        with self._lock:
            return json.loads(QUEUE_FILE.read_text())

    def _save_q(self, queue: List[Dict]):
        with self._lock:
            QUEUE_FILE.write_text(json.dumps(queue, indent=2))

    def add_to_queue(self, item_id: str, content_type: str = ""):
        queue = self._load()
        queue.append({
            "id": item_id, "type": content_type,
            "status": "pending_review", "added_at": datetime.now().isoformat(),
        })
        self._save_q(queue)

    def get_pending_review(self) -> List[Dict]:
        return [i for i in self._load() if i["status"] == "pending_review"]

    def approve(self, item_id: str):
        queue = self._load()
        for item in queue:
            if item["id"] == item_id:
                item["status"] = "approved"
        self._save_q(queue)

    def reject(self, item_id: str):
        queue = self._load()
        for item in queue:
            if item["id"] == item_id:
                item["status"] = "rejected"
        self._save_q(queue)

    def get_approved(self) -> List[Dict]:
        return [i for i in self._load() if i["status"] == "approved"]
