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
from app.ai.reference_library import get_references_for_project


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 + curated sector library
    references = _collect_references(market_data, financial_data, competitive_data, synthesis_data, project_name, project_description)

    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}


TRUSTED_REFERENCE_DOMAINS = {
    "worldbank.org",
    "imf.org",
    "oecd.org",
    "who.int",
    "un.org",
    "unesco.org",
    "wto.org",
    "weforum.org",
    "bloomberg.com",
    "reuters.com",
    "forbes.com",
    "wsj.com",
    "ft.com",
    "economist.com",
    "statista.com",
    "gartner.com",
    "mckinsey.com",
    "deloitte.com",
    "pwc.com",
    "ey.com",
    "kpmg.com",
    "bcg.com",
    "accenture.com",
    "gov.sa",
    "my.gov.sa",
    "sama.gov.sa",
    "mc.gov.sa",
    "mof.gov.sa",
    "mci.gov.sa",
    "sagia.gov.sa",
    "nct.gov.sa",
    "vision2030.gov.sa",
    "investsaudi.sa",
    "argaam.com",
    "ncb.gov.sa",
    "capmas.gov.eg",
    "cbe.org.eg",
    "mcit.gov.eg",
    "sis.gov.eg",
    "planning.gov.eg",
    "nbee.gov.eg",
    "usa.gov",
    "data.gov",
    "census.gov",
    "bea.gov",
    "bls.gov",
    "sec.gov",
    "ecb.europa.eu",
    "europa.eu",
    "eurostat.ec.europa.eu",
    "nber.org",
    "pnas.org",
    "sciencedirect.com",
    "springer.com",
    "tandfonline.com",
    "emerald.com",
    "hbr.org",
    "sbir.gov",
    "startupgenome.com",
    "crunchbase.com",
    "pitchbook.com",
    "cbinsights.com",
    "techcrunch.com",
    "wired.com",
}

CURATED_ONLY_DOMAINS = {
    "mckinsey.com", "deloitte.com", "pwc.com", "ey.com", "kpmg.com",
    "bcg.com", "accenture.com", "gartner.com", "forrester.com",
    "forbes.com", "bloomberg.com", "wsj.com", "ft.com",
    "statista.com", "crunchbase.com", "pitchbook.com", "cbinsights.com",
    "oecd.org", "weforum.org", "economist.com",
    "worldbank.org",
}


CURATED_REFERENCE_LIBRARY = {
    "world bank": {"title": "World Bank Open Data", "url": "https://data.worldbank.org"},
    "imf": {"title": "International Monetary Fund - Data", "url": "https://www.imf.org/en/Data"},
    "oecd": {"title": "OECD Data Explorer", "url": "https://data-explorer.oecd.org"},
    "oecd country": {"title": "OECD - Saudi Arabia Economic Survey", "url": "https://www.oecd.org/en/countries/saudi-arabia.html"},
    "statista": {"title": "Statista - Market Data", "url": "https://www.statista.com"},
    "gartner": {"title": "Gartner - Market Analysis", "url": "https://www.gartner.com/en/research"},
    "mckinsey": {"title": "McKinsey & Company - Insights", "url": "https://www.mckinsey.com/featured-insights"},
    "deloitte": {"title": "Deloitte Insights", "url": "https://www.deloitte.com/insights"},
    "pwc": {"title": "PwC - Reports & Publications", "url": "https://www.pwc.com/gx/en/research-insights.html"},
    "sama": {"title": "Saudi Central Bank - Reports & Statistics", "url": "https://www.sama.gov.sa/en-US/EconomicReports"},
    "vision 2030": {"title": "Saudi Vision 2030", "url": "https://www.vision2030.gov.sa"},
    "bloomberg": {"title": "Bloomberg - Markets", "url": "https://www.bloomberg.com/markets"},
    "forbes": {"title": "Forbes - Business", "url": "https://www.forbes.com/business"},
    "wsj": {"title": "The Wall Street Journal", "url": "https://www.wsj.com"},
    "ft": {"title": "Financial Times", "url": "https://www.ft.com"},
    "world economic forum": {"title": "World Economic Forum - Reports", "url": "https://www.weforum.org/reports"},
    "hbr": {"title": "Harvard Business Review", "url": "https://hbr.org"},
    "crunchbase": {"title": "Crunchbase - Company Data", "url": "https://www.crunchbase.com"},
    "cb insights": {"title": "CB Insights - Research", "url": "https://www.cbinsights.com/research"},
    "pitchbook": {"title": "PitchBook - Data & Research", "url": "https://pitchbook.com"},
    "sciencedirect": {"title": "ScienceDirect", "url": "https://www.sciencedirect.com"},
    "springer": {"title": "Springer - Academic Publishing", "url": "https://www.springer.com"},
    "google scholar": {"title": "Google Scholar", "url": "https://scholar.google.com"},
    "who": {"title": "World Health Organization - Data", "url": "https://www.who.int/data"},
    "un": {"title": "United Nations - Data", "url": "https://data.un.org"},
    "invest saudi": {"title": "Invest Saudi", "url": "https://investsaudi.sa"},
    "argaam": {"title": "Argaam - Financial Data", "url": "https://www.argaam.com"},
}


SUSPICIOUS_PATH_PATTERNS = [
    r"12345678", r"1234567", r"123456", r"000000", r"111111",
    r"xxxxx", r"test", r"sample", r"example", r"placeholder",
    r"your-company", r"your-brand", r"my-project",
]


def _normalize_url(url: str) -> str:
    """Ensure URL has a scheme and is properly formatted."""
    url = url.strip().strip('"').strip("'")
    if not url:
        return ""
    if not url.startswith(("http://", "https://")):
        url = "https://" + url
    return url


def _is_suspicious_url(url: str) -> bool:
    """Detect AI-hallucinated URLs with fake paths/IDs."""
    from urllib.parse import urlparse
    import re
    try:
        parsed = urlparse(url)
        path = parsed.path + "?" + parsed.query if parsed.query else parsed.path
        for pattern in SUSPICIOUS_PATH_PATTERNS:
            if re.search(pattern, path, re.IGNORECASE):
                return True
        return False
    except Exception:
        return False


def _is_curated_only_domain(url: str) -> bool:
    """Check if URL is on a domain that only allows curated URLs (no AI paths)."""
    from urllib.parse import urlparse
    try:
        parsed = urlparse(url)
        domain = parsed.netloc.lower()
        if domain.startswith("www."):
            domain = domain[4:]
        for curated_domain in CURATED_ONLY_DOMAINS:
            if domain == curated_domain or domain.endswith("." + curated_domain):
                return True
    except Exception:
        pass
    return False


def _is_trusted_domain(url: str) -> bool:
    """Check if a URL belongs to a trusted domain."""
    from urllib.parse import urlparse
    try:
        parsed = urlparse(url)
        domain = parsed.netloc.lower()
        if domain.startswith("www."):
            domain = domain[4:]
        for trusted in TRUSTED_REFERENCE_DOMAINS:
            if domain == trusted or domain.endswith("." + trusted):
                return True
    except Exception:
        pass
    return False


def _lookup_suggested_url(title: str, url: str) -> str:
    """Try to find a curated URL. If AI's URL is suspicious, use curated one."""
    lower_title = (title or "").lower()

    # Try curated library match first by keyword
    for keyword, curated in CURATED_REFERENCE_LIBRARY.items():
        if keyword in lower_title:
            return curated["url"]

    # Reject AI-generated paths on curated-only domains (paywalled/consulting)
    if url and _is_curated_only_domain(url):
        return ""

    # Accept AI URL if on trusted domain with specific path and not suspicious
    if url and _is_trusted_domain(url) and not _is_suspicious_url(url):
        return url

    return ""


def _filter_and_fix_references(references: list) -> list:
    """Filter out hallucinated references, fix URLs, and return cleaned list."""
    cleaned = []
    for ref in references:
        if not isinstance(ref, dict):
            cleaned.append(ref)
            continue

        title = ref.get("title", ref.get("text", ""))
        url = ref.get("url", "")

        if url:
            url = _normalize_url(url)
            ref["url"] = _lookup_suggested_url(title, url)
            if ref["url"]:
                cleaned.append(ref)
            # No URL → skip entirely (remove text-only entries)

    if not cleaned:
        cleaned = _get_default_fallback_references()

    for ref in cleaned:
        if isinstance(ref, dict) and ref.get("title") and not ref.get("description"):
            ref["description"] = ref.get("source", "")

    return cleaned


def _get_default_fallback_references() -> list:
    """Return pre-verified fallback references with real, working URLs."""
    return [
        {
            "source": "General",
            "title": "Industry standard business analysis frameworks (SWOT, PESTEL, Porter's Five Forces)",
            "url": "https://hbr.org/1979/01/how-competitive-forces-shape-strategy",
            "description": "Harvard Business Review - Michael Porter's competitive analysis framework",
        },
        {
            "source": "General",
            "title": "Business Model Generation: A Handbook for Visionaries",
            "url": "https://www.strategyzer.com/books/business-model-generation",
            "description": "Strategyzer - Business Model Canvas methodology by Osterwalder & Pigneur",
        },
        {
            "source": "General",
            "title": "The Lean Startup methodology",
            "url": "https://theleanstartup.com/principles",
            "description": "Eric Ries - Lean Startup principles for building and managing startups",
        },
        {
            "source": "General",
            "title": "TAM SAM SOM Market Sizing Methodology",
            "url": "https://www.investopedia.com/terms/t/total-addressable-market-tam.asp",
            "description": "Investopedia - Market sizing framework explained",
        },
    ]


def _collect_references(market_data: dict, financial_data: dict, competitive_data: dict, synthesis_data: dict,
                        project_name: str = "", project_description: str = "") -> list:
    """Collect references from AI analysis results + curated sector library."""
    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")

    # Validate and fix URLs in AI-generated references
    references = _filter_and_fix_references(references)

    # Append curated sector-matched references (guaranteed real URLs)
    if project_name or project_description:
        curated = get_references_for_project(project_name, project_description)
        seen_urls = {r.get("url", "").rstrip("/") for r in references if r.get("url")}
        for ref in curated:
            url = ref.get("url", "").rstrip("/")
            if url and url not in seen_urls:
                seen_urls.add(url)
                references.append(ref)

    # Final dedup by URL + title (remove exact duplicates)
    seen = set()
    deduped = []
    for ref in references:
        key = (ref.get("url", ""), ref.get("title", ""))
        if key not in seen:
            seen.add(key)
            deduped.append(ref)

    return deduped


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)
