import asyncio
import sys
import json
from app.ai.providers import get_provider, get_fast_model, get_deep_model, get_screen_config

if sys.platform == "win32":
    asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy())
from app.ai.prompts.market_logic import get_market_logic_prompt
from app.ai.prompts.financial import get_financial_prompt
from app.ai.prompts.competitive import get_competitive_prompt
from app.ai.prompts.synthesis import get_synthesis_prompt


async def run_diamond(project_name: str, project_description: str, language: str = "ar", user_note: str = None) -> dict:
    # Use plan-based config if available, otherwise fall back to defaults
    cfg = get_screen_config("feasibility_study")
    provider = get_provider(cfg["provider"], cfg.get("api_key"))
    fast_model = cfg.get("model") or get_fast_model()
    deep_model = get_deep_model()

    # Check if there's a separate deep model config (same screen, higher tier)
    try:
        from flask_login import current_user
        plan_name = current_user.active_plan.name if current_user.active_plan else "free"
    except Exception:
        plan_name = "free"

    # For synthesis (deep), try to get a dedicated config
    synthesis_cfg = get_screen_config("feasibility_study", plan_name)
    synthesis_provider = get_provider(synthesis_cfg["provider"], synthesis_cfg.get("api_key"))
    synthesis_model = synthesis_cfg.get("model") or deep_model
    synthesis_temp = synthesis_cfg.get("temperature", 0.5)

    market_msgs = get_market_logic_prompt(project_name, project_description, language, user_note)
    financial_msgs = get_financial_prompt(project_name, project_description, language, user_note)
    competitive_msgs = get_competitive_prompt(project_name, project_description, language, user_note)

    market_raw, financial_raw, competitive_raw = await asyncio.gather(
        provider.chat(market_msgs, fast_model, temperature=cfg.get("temperature", 0.7)),
        provider.chat(financial_msgs, fast_model, temperature=cfg.get("temperature", 0.7)),
        provider.chat(competitive_msgs, fast_model, temperature=cfg.get("temperature", 0.7)),
    )

    market_data = _parse_json(market_raw)
    financial_data = _parse_json(financial_raw)
    competitive_data = _parse_json(competitive_raw)

    synthesis_msgs = get_synthesis_prompt(
        project_name, project_description,
        market_raw, financial_raw, competitive_raw, language, user_note,
    )
    synthesis_raw = await synthesis_provider.chat(
        synthesis_msgs, synthesis_model, temperature=synthesis_temp
    )
    synthesis_data = _parse_json(synthesis_raw)

    # Collect references from all analyses
    references = _collect_references(market_data, financial_data, competitive_data, synthesis_data)

    return {
        "market_analysis": market_data,
        "financial_analysis": financial_data,
        "competitive_analysis": competitive_data,
        "synthesis": synthesis_data,
        "verdict": synthesis_data.get("verdict", "UNKNOWN") if isinstance(synthesis_data, dict) else "UNKNOWN",
        "references": references,
    }


def _parse_json(text: str) -> dict:
    text = text.strip()
    if text.startswith("```"):
        lines = text.split("\n")
        lines = lines[1:] if lines[0].startswith("```") else lines
        end_idx = len(lines)
        for i, line in enumerate(lines):
            if line.strip() == "```":
                end_idx = i
                break
        text = "\n".join(lines[:end_idx])
    try:
        return json.loads(text)
    except json.JSONDecodeError:
        return {"raw_text": text}


def _collect_references(market_data: dict, financial_data: dict, competitive_data: dict, synthesis_data: dict) -> list:
    """Collect references from all analysis results."""
    references = []

    def add_refs_from_data(data, source_prefix):
        if not isinstance(data, dict):
            return
        if "references" in data and isinstance(data["references"], list):
            for ref in data["references"]:
                if isinstance(ref, dict):
                    ref["source"] = source_prefix
                    references.append(ref)
                elif isinstance(ref, str):
                    references.append({"source": source_prefix, "text": ref})
        if "sources" in data and isinstance(data["sources"], list):
            for ref in data["sources"]:
                if isinstance(ref, dict):
                    ref["source"] = source_prefix
                    references.append(ref)
                elif isinstance(ref, str):
                    references.append({"source": source_prefix, "text": ref})

    add_refs_from_data(market_data, "Market Analysis")
    add_refs_from_data(financial_data, "Financial Analysis")
    add_refs_from_data(competitive_data, "Competitive Analysis")
    add_refs_from_data(synthesis_data, "Synthesis")

    # Add general industry/analytical references if none provided
    if not references:
        general_refs = [
            {"source": "General", "text": "Industry standard business analysis frameworks (SWOT, PESTEL, Porter's Five Forces)"},
            {"source": "General", "text": "Financial modeling best practices for startup feasibility"},
            {"source": "General", "text": "Market sizing methodologies (TAM/SAM/SOM)"},
            {"source": "General", "text": "Business Model Canvas and Lean Canvas methodologies"},
        ]
        references.extend(general_refs)

    return references


async def call_ai(messages: list, model_type: str = "fast") -> str:
    provider = get_provider()
    model = get_fast_model() if model_type == "fast" else get_deep_model()
    return await provider.chat(messages, model, temperature=0.7)


def run_sync(coro):
    try:
        loop = asyncio.get_running_loop()
    except RuntimeError:
        loop = None
    if loop and loop.is_running():
        import concurrent.futures
        with concurrent.futures.ThreadPoolExecutor() as pool:
            future = pool.submit(asyncio.run, coro)
            return future.result()
    else:
        return asyncio.run(coro)
