"""
Wikidata company domain index loader for company-to-domain lookups.
"""

from __future__ import annotations

import json
import os
import re
import threading
from pathlib import Path
from typing import Optional
import logging

logger = logging.getLogger(__name__)

# Global cache
_INDEX_CACHE: Optional[dict] = None
_INDEX_LOCK = threading.RLock()

# Lazy import duckdb
try:
    import duckdb

    HAS_DUCKDB = True
except ImportError:
    HAS_DUCKDB = False
    logger.debug("duckdb not available, Wikidata index disabled")

# Serving connection (lazy-loaded; avoid cycles on startup)
try:
    from ..services import foundrygraph_serving
except Exception as exc:  # pragma: no cover - defensive
    foundrygraph_serving = None
    logger.debug("foundrygraph_serving unavailable: %s", exc)


RAW_LEGAL_SUFFIXES = [
    "S.A. de C.V.",
    "SA de CV",
    "Private Limited",
    "Pty Ltd",
    "Pty. Ltd.",
    "Pvt Ltd",
    "Pvt. Ltd.",
    "Incorporated",
    "Corporation",
    "Limited",
    "Company",
    "S.A.S.",
    "S.A.R.L.",
    "S.A.",
    "S.p.A.",
    "S.r.l.",
    "B.V.",
    "N.V.",
    "A.S.",
    "A/S",
    "Inc.",
    "Inc",
    "Corp.",
    "Corp",
    "Ltd.",
    "Ltd",
    "LLC",
    "L.L.C.",
    "LLP",
    "L.L.P.",
    "Co.",
    "Co",
    "PLC",
    "P.L.C.",
    "BV",
    "NV",
    "SAS",
    "SARL",
    "SA",
    "SPA",
    "SRL",
    "SL",
    "S.L.",
    "AS",
    "Pty",
    "Pty.",
    "Pvt",
    "Pvt.",
    "GmbH",
    "AG",
    "KG",
    "Group",
    "Holdings",
    "International",
    "Global",
]

_NORMALIZED_LEGAL_SUFFIXES = sorted(
    {suffix.lower() for suffix in RAW_LEGAL_SUFFIXES}, key=len, reverse=True
)

_LEGAL_SUFFIX_PATTERN = re.compile(
    r"\s+("
    + "|".join(re.escape(suffix) for suffix in _NORMALIZED_LEGAL_SUFFIXES)
    + r")$",
    re.IGNORECASE,
)


def normalize_company_name(name: str) -> str:
    """Normalize company name to match Wikidata index format."""
    if not name:
        return ""
    name = name.lower().strip()
    # Remove legal suffixes
    while True:
        updated = _LEGAL_SUFFIX_PATTERN.sub("", name).strip()
        if updated == name:
            break
        name = updated
    return name


def load_wikidata_index(db_path: str) -> dict:
    """
    Load Wikidata company index into memory for fast lookups.

    Returns dict of {normalized_name: domain}
    """
    if not HAS_DUCKDB:
        return {}

    if not Path(db_path).exists():
        logger.debug(f"Wikidata index not found: {db_path}")
        return {}

    try:
        conn = duckdb.connect(db_path, read_only=True)

        # Load all records into memory
        results = conn.execute(
            "SELECT normalized_name, domain, confidence FROM company_domains ORDER BY confidence DESC"
        ).fetchall()

        # Build lookup dict (prefer higher confidence for duplicates)
        index = {}
        for norm_name, domain, conf in results:
            if norm_name not in index:
                index[norm_name] = domain

        conn.close()

        logger.info(f"Loaded Wikidata index: {len(index)} companies from {db_path}")
        return index

    except Exception as e:
        logger.warning(f"Failed to load Wikidata index from {db_path}: {e}")
        return {}


def get_wikidata_index() -> dict:
    """Get cached Wikidata index, loading if necessary."""
    global _INDEX_CACHE

    with _INDEX_LOCK:
        if _INDEX_CACHE is None:
            db_path = os.getenv(
                "WIKIDATA_INDEX_PATH", "config/foundrygraph.duckdb"
            )
            _INDEX_CACHE = load_wikidata_index(db_path)

        return _INDEX_CACHE


def lookup_company_domain(company_name: str) -> Optional[str]:
    """
    Lookup domain for a company in Wikidata index.

    Args:
        company_name: Company name to lookup

    Returns:
        Domain if found, None otherwise
    """
    if not company_name:
        return None

    index = get_wikidata_index()
    if not index:
        return None

    normalized = normalize_company_name(company_name)
    return index.get(normalized)


def reload_index():
    """Force reload of Wikidata index (e.g., after update)."""
    global _INDEX_CACHE
    with _INDEX_LOCK:
        _INDEX_CACHE = None
    get_wikidata_index()  # Trigger reload


def _safe_parse_json(value):
    """Parse JSON-ish DuckDB values safely."""
    if value is None:
        return None
    if isinstance(value, (dict, list)):
        return value
    try:
        return json.loads(value)
    except Exception:
        return value


def search_companies(query: str, limit: int = 20, include_aliases: bool = True) -> list[dict]:
    """
    Lightweight name search against the DuckDB artifact.

    Uses company_profiles.label today; aliases can be added later by joining the aliases table.
    """
    if not HAS_DUCKDB or not foundrygraph_serving:
        logger.warning("DuckDB/serving unavailable; search returning empty list")
        return []

    conn = foundrygraph_serving.get_foundrygraph_connection()
    term = f"%{query.lower()}%"

    sql = """
    SELECT
      wikidata_id,
      label,
      domain,
      industries,
      headquarters,
      quality_score
    FROM company_profiles
    WHERE lower(label) LIKE ?
    ORDER BY quality_score DESC NULLS LAST
    LIMIT ?
    """

    rows = conn.execute(sql, [term, limit]).fetchall()
    cols = [c[0] for c in conn.description]

    results = []
    for row in rows:
        record = dict(zip(cols, row))
        record["industries"] = _safe_parse_json(record.get("industries"))
        record["headquarters"] = _safe_parse_json(record.get("headquarters"))
        results.append(record)

    return results
