from __future__ import annotations

import hashlib
import json
import time
from typing import Any, Dict, List, Optional
from urllib.parse import urljoin

from src.fmatch.ingest.connector_sdk.base import ConnectorBase, FetchResult

API_BASE = "https://api.opencorporates.com/v0.4"


class OpenCorporatesConnector(ConnectorBase):
    """Incremental pull from OpenCorporates (non-authoritative seed)."""

    def __init__(self, http_client: Any, since_hours: int = 6) -> None:
        self.http = http_client
        self.since_hours = since_hours

    def checkpoint_key(self) -> str:
        return "OPENCO"

    def fetch(
        self,
        *,
        batch_id: Optional[str] = None,
        next_token: Optional[str] = None,
        resume: bool = False,
    ) -> FetchResult:
        if next_token:
            response = self.http.get(next_token, timeout=30)
        else:
            params = {"updated_since": f"{self.since_hours}h"}
            response = self.http.get(
                f"{API_BASE}/companies/search", params=params, timeout=30
            )
        response.raise_for_status()
        payload = response.json()
        result_info = payload.get("results", {}) or {}
        items = result_info.get("companies", [])
        next_url = (
            result_info.get("next_url")
            or result_info.get("next_page_url")
            or payload.get("next")
            or payload.get("page", {}).get("next")
        )
        if next_url and not next_url.startswith("http"):
            next_url = urljoin(API_BASE, next_url)
        return FetchResult(
            items=items, next_token=next_url, batch_id=str(int(time.time()))
        )

    def process(self, *, item: Dict[str, Any]) -> Dict[str, Any]:
        raw_payload = item
        company = raw_payload.get("company", {})
        jurisdiction = (company.get("jurisdiction_code") or "").upper()
        company_number = company.get("company_number") or ""

        sha256 = hashlib.sha256(
            json.dumps(raw_payload, sort_keys=True).encode("utf-8")
        ).hexdigest()
        seen_at = company.get("updated_at") or company.get("created_at")

        source_event = {
            "source": "OPENCO",
            "jurisdiction": jurisdiction,
            "raw_id": str(company_number),
            "raw_payload": raw_payload,
            "seen_at": seen_at,
            "sha256": sha256,
            "license_tag": "restricted",
        }

        ids = []
        if company_number:
            ids.append(
                {
                    "type": "OPENCO",
                    "value": str(company_number),
                    "issuer": jurisdiction or None,
                }
            )
        if jurisdiction:
            ids.append({"type": "JURISDICTION", "value": jurisdiction})

        url_candidates = [
            company.get("company_website"),
            company.get("home_page"),
            company.get("homepage"),
            company.get("website"),
            company.get("registry_url"),
        ]
        urls: List[str] = []
        for candidate in url_candidates:
            if not isinstance(candidate, str):
                continue
            normalized = candidate.strip()
            if not normalized:
                continue
            if normalized.startswith("//"):
                normalized = f"https:{normalized}"
            if not normalized.startswith(("http://", "https://")):
                normalized = f"https://{normalized}"
            if normalized not in urls:
                urls.append(normalized)

        normalized_entity = {
            "legal_name": company.get("name") or "",
            "country_code": (company.get("registered_address") or {}).get(
                "country_code"
            ),
            "status": (company.get("current_status") or "unknown").lower(),
            "ids": ids,
            "urls": urls,
            "updated_at": seen_at,
        }

        evidence = {
            "entity_key": sha256,
            "source": "OPENCO",
            "evidence_type": "opencorp_seed",
            "payload": {
                "name": company.get("name"),
                "number": company_number,
                "jurisdiction": jurisdiction,
            },
            "seen_at": seen_at,
            "license_tag": "restricted",
        }

        return {
            "source_event": source_event,
            "normalized_entity": normalized_entity,
            "promotion_evidence": evidence,
        }
