import json
import re
from datetime import datetime

from app.core.timezone import SANTIAGO
from app.services.document_service import MONTHS_ES, render_template_content


def _semantic_tokens(*values: object) -> set[str]:
    source = "_".join(str(value or "") for value in values)
    source = re.sub(r"([a-z0-9])([A-Z])", r"\1_\2", source)
    return {token for token in re.split(r"[^a-zA-Z0-9áéíóúñÁÉÍÓÚÑ]+", source.lower()) if token}


def _first_option(raw: object) -> str | None:
    if not raw:
        return None
    try:
        options = json.loads(raw) if isinstance(raw, str) else raw
    except (TypeError, ValueError):
        return None
    if not isinstance(options, list) or not options:
        return None
    first = options[0]
    if isinstance(first, dict):
        first = first.get("label") or first.get("nombre") or first.get("value")
    return str(first).strip() if first is not None and str(first).strip() else None


def sample_field_value(field: dict, preview_date: datetime) -> str:
    code = str(field.get("codigo") or "")
    label = str(field.get("etiqueta") or code or "campo")
    field_type = str(field.get("tipo_dato") or "TEXTO").upper()
    tokens = _semantic_tokens(code, label)
    option = _first_option(field.get("opciones_json"))

    if field_type in {"RUT", "RUT_CHILENO", "RUT CHILENO"} or "rut" in tokens:
        return "12.345.678-5"
    if field_type == "EMAIL" or tokens.intersection({"email", "correo"}):
        return "cliente@ejemplo.cl"
    if field_type == "TELEFONO" or tokens.intersection({"telefono", "celular", "fono"}):
        return "+56 9 1234 5678"
    if field_type == "FECHA":
        return preview_date.strftime("%d-%m-%Y")
    if field_type == "FECHA_HORA":
        return preview_date.strftime("%d-%m-%Y %H:%M")
    if field_type == "BOOLEANO":
        return "Sí"
    if field_type == "LISTA" and option:
        return option
    if field_type == "COMUNA" or "comuna" in tokens:
        return "Santiago"
    if field_type == "ENTERO":
        return "1"
    if field_type == "DECIMAL" or tokens.intersection({"monto", "valor", "precio"}):
        return "100000"
    if field_type == "ARCHIVO":
        return "documento-ejemplo.pdf"
    if "direccion" in tokens or "domicilio" in tokens:
        return "Avenida Principal 123"
    if "ciudad" in tokens:
        return "Santiago"
    if "region" in tokens:
        return "Región Metropolitana de Santiago"
    if "nacionalidad" in tokens:
        return "chilena"
    if "profesion" in tokens:
        return "ingeniera comercial"
    if "civil" in tokens:
        return "soltera"
    if tokens.intersection({"rol", "avaluo"}):
        return "123-45"
    if tokens.intersection({"actividad", "giro"}):
        return "servicios profesionales"
    if tokens.intersection({"apellido", "apellidos"}):
        return "González Soto"
    if tokens.intersection({"nombre", "nombres"}):
        return "María Fernanda González Soto"
    if field_type == "TEXTO_LARGO":
        return f"Texto de ejemplo para {label.lower()}"
    return f"Ejemplo de {label.lower()}"


def render_template_preview(content: str, matter_name: str, fields: list[dict],
                            entity: dict | None = None,
                            preview_date: datetime | None = None) -> str:
    now = preview_date or datetime.now(SANTIAGO)
    if now.tzinfo is None:
        now = now.replace(tzinfo=SANTIAGO)
    long_date = f"{now.day} de {MONTHS_ES[now.month - 1]} de {now.year}"
    entity = entity or {}
    entity_name = str(entity.get("nombre_fantasia") or "Entidad de ejemplo")
    entity_address = str(entity.get("direccion") or "Avenida Principal 123")
    entity_commune = str(entity.get("comuna") or "Santiago")
    entity_city = str(entity.get("ciudad") or entity_commune)
    entity_region = str(entity.get("region") or "Región Metropolitana de Santiago")

    variables: dict[str, object] = {
        "folio": "DOC-VISTA-PREVIA",
        "materia.nombre": matter_name,
        "documento.fecha": now.strftime("%d-%m-%Y"),
        "documento.fecha.larga": long_date,
        "fecha.hoy": now.strftime("%d-%m-%Y"),
        "ot.fecha": now.strftime("%d-%m-%Y"),
        "ot.fecha.larga": long_date,
        "notaria.nombre": entity_name,
        "notaria.direccion": entity_address,
        "notaria.comuna": entity_commune,
        "notaria.ciudad": entity_city,
        "notaria.region": entity_region,
        "entidad.nombre": entity_name,
        "entidad.direccion": entity_address,
        "entidad.comuna": entity_commune,
        "entidad.ciudad": entity_city,
        "entidad.region": entity_region,
        "cliente.nombres": "María Fernanda",
        "cliente.apellidos": "González Soto",
        "cliente.nombre_completo": "María Fernanda González Soto",
        "cliente.rut": "12.345.678-5",
        "cliente.email": "cliente@ejemplo.cl",
        "cliente.telefono": "+56 9 1234 5678",
        "campo.cliente_nombre_completo": "María Fernanda González Soto",
        "campo.cliente_rut": "12.345.678-5",
        "campo.cliente_email": "cliente@ejemplo.cl",
        "campo.cliente_telefono": "+56 9 1234 5678",
        "compareciente.1.nombre": "María Fernanda González Soto",
        "compareciente.1.nombreInformal": "María Fernanda González Soto",
        "compareciente.1.nombres": "María Fernanda",
        "compareciente.1.apellidos": "González Soto",
        "compareciente.1.rut": "12.345.678-5",
        "compareciente.1.email": "cliente@ejemplo.cl",
        "compareciente.1.telefono": "+56 9 1234 5678",
    }
    active_fields = [field for field in fields if bool(field.get("activo", True))]
    field_values = {
        str(field["codigo"]): sample_field_value(field, now)
        for field in active_fields
    }
    field_types = {
        str(field["codigo"]): str(field.get("tipo_dato") or "TEXTO")
        for field in active_fields
    }
    return render_template_content(content, variables, field_values, field_types)
