from __future__ import annotations

from datetime import date
from typing import Dict, Any, Optional

from src.infra.document_analysis.models.company_profile import CompanyProfile
from src.infra.document_analysis.normalizers.company_name_normalizer import normalize_company_name
from src.infra.document_analysis.normalizers.date_normalizer import parse_date_flexible, months_since


def _safe_float(x: Any, default: float = 0.0) -> float:
    try:
        return float(x)
    except Exception:
        return default


def _extract_entity_type_sigla(text: Optional[str]) -> Optional[str]:
    """Extrai sigla (LDA, SA) de uma descrição ou nome."""
    if not text:
        return None
    text = text.upper()
    if "LDA" in text:
        return "LDA"
    if "LIMITADA" in text:
        return "LDA"
    if "SA" in text or "S.A." in text:
        return "SA"
    if "SU, LDA" in text:
        return "LDA"
    return None


def build_profile_from_alvara(features: Dict[str, Any], entities: Dict[str, Any]) -> CompanyProfile:
    raw = features or {}

    company_name = normalize_company_name(raw.get("company_name") or entities.get("company_name"))
    nuit = raw.get("nuit") or entities.get("nuit")

    # Tenta inferir entity_type do nome da empresa
    entity_type = _extract_entity_type_sigla(company_name)

    # Data de emissão do alvará (não é data de constituição)
    # Incorporation_date não disponível no alvará
    incorporation_date = None
    company_age_months = None

    issuer = raw.get("issuer") or entities.get("issuer")
    confidence = _safe_float(raw.get("confidence"), 0.0)

    # Adiciona campos específicos ao raw (já estão, mas garantimos)
    raw["alvara_number"] = raw.get("alvara_number")
    raw["decreto_number"] = raw.get("decreto_number")
    raw["atividade_principal"] = raw.get("atividade_principal")
    raw["endereco"] = raw.get("endereco")
    raw["data_emissao"] = raw.get("data_emissao")
    raw["codigo_verificacao"] = raw.get("codigo_verificacao")
    raw["validity_status"] = raw.get("validity_status")

    return CompanyProfile(
        source="alvara",
        company_name=company_name,
        entity_type=entity_type,
        nuit=str(nuit) if nuit else None,
        incorporation_date=incorporation_date,
        company_age_months=company_age_months,
        issuer=issuer,
        confidence=confidence,
        raw=raw,
    )


def build_profile_from_certidao(features: Dict[str, Any], entities: Dict[str, Any]) -> CompanyProfile:
    raw = features or {}

    company_name = normalize_company_name(raw.get("company_name") or entities.get("company_name"))
    # entity_type pode vir como sigla (raw["entity_type"]) ou descrição completa
    entity_type_sigla = raw.get("entity_type")  # já é sigla (LDA) no analyzer atual
    if not entity_type_sigla:
        entity_type_sigla = _extract_entity_type_sigla(raw.get("entity_type_description") or entities.get("entity_type"))

    nuit = raw.get("nuit") or entities.get("nuit")  # cuidado: na certidão não há NUIT, mas pode vir de entidades erroneamente

    # Data de constituição (confiável)
    incorporation_date = raw.get("incorporation_date")
    if isinstance(incorporation_date, str):
        incorporation_date = parse_date_flexible(incorporation_date)

    company_age_months = raw.get("company_age_months")
    if (company_age_months is None or company_age_months == 0) and isinstance(incorporation_date, date):
        company_age_months = months_since(incorporation_date)

    issuer = raw.get("issuer") or entities.get("issuer")
    confidence = _safe_float(raw.get("confidence"), 0.0)

    # Campos específicos
    raw["entity_legal_number"] = raw.get("entity_legal_number")
    raw["capital_social"] = raw.get("capital_social")
    raw["capital_realizado"] = raw.get("capital_realizado")
    raw["beneficiarios_efectivos"] = raw.get("beneficiarios_efectivos")
    raw["administrator"] = raw.get("administrator")
    raw["issuance_date"] = raw.get("issuance_date")

    return CompanyProfile(
        source="certidao_registo",
        company_name=company_name,
        entity_type=entity_type_sigla,
        nuit=str(nuit) if nuit else None,
        incorporation_date=incorporation_date if isinstance(incorporation_date, date) else None,
        company_age_months=company_age_months,
        issuer=issuer,
        confidence=confidence,
        raw=raw,
    )


def build_profile_from_nuit(features: Dict[str, Any], entities: Dict[str, Any]) -> CompanyProfile:
    raw = features or {}

    company_name = normalize_company_name(raw.get("company_name") or entities.get("company_name"))
    # entity_type pode vir como descrição completa, extrair sigla
    entity_type_sigla = _extract_entity_type_sigla(raw.get("entity_type") or entities.get("entity_type"))
    nuit = raw.get("nuit") or entities.get("nuit")

    # Data de constituição (confiável)
    incorporation_date = raw.get("incorporation_date")
    if isinstance(incorporation_date, str):
        incorporation_date = parse_date_flexible(incorporation_date)

    company_age_months = raw.get("company_age_months")
    if company_age_months is None and isinstance(incorporation_date, date):
        company_age_months = months_since(incorporation_date)

    issuer = raw.get("issuer") or entities.get("issuer")
    confidence = _safe_float(raw.get("confidence"), 0.0)

    # Campos específicos
    raw["trade_name"] = raw.get("trade_name")
    raw["incorporation_date_str"] = raw.get("incorporation_date_str")
    raw["issuer_valid"] = raw.get("issuer_valid")
    raw["subject_valid"] = raw.get("subject_valid")

    return CompanyProfile(
        source="nuit",
        company_name=company_name,
        entity_type=entity_type_sigla,
        nuit=str(nuit) if nuit else None,
        incorporation_date=incorporation_date if isinstance(incorporation_date, date) else None,
        company_age_months=company_age_months,
        issuer=issuer,
        confidence=confidence,
        raw=raw,
    )


def build_profile_from_input(input_data: Dict[str, Any]) -> CompanyProfile:
    company_name = normalize_company_name(input_data.get("company_name"))
    entity_type = _extract_entity_type_sigla(input_data.get("entity_type"))
    nuit = input_data.get("nuit")

    incorporation_date = input_data.get("incorporation_date")
    if isinstance(incorporation_date, str):
        incorporation_date = parse_date_flexible(incorporation_date)

    company_age_months = input_data.get("months_activity")
    issuer = "user_input"

    return CompanyProfile(
        source="input",
        company_name=company_name,
        entity_type=entity_type,
        nuit=str(nuit) if nuit else None,
        incorporation_date=incorporation_date if isinstance(incorporation_date, date) else None,
        company_age_months=company_age_months,
        issuer=issuer,
        confidence=1.0,
        raw=input_data,
    )