"""Sanitiza URLs de ofertas: nunca abrir example.com ni placeholders."""

from __future__ import annotations

from typing import Any
from urllib.parse import quote_plus, urlparse

DUMMY_HOSTS = {
    "example.com",
    "www.example.com",
    "example.org",
    "www.example.org",
    "example.net",
    "www.example.net",
    "test.com",
    "www.test.com",
    "localhost",
}

_FALLBACK_TEMPLATES = {
    "infojobs": "https://www.infojobs.net/jobsearch/search-results/list.xhtml?keyword={query}",
    "indeed": "https://es.indeed.com/jobs?q={query}&l={location}",
    "tecnoempleo": "https://www.tecnoempleo.com/ofertas-trabajo/{query}",
    "linkedin": "https://www.linkedin.com/jobs/search/?keywords={query}&location={location}",
    "infoempleo": "https://www.infoempleo.com/trabajo/{query}/",
    "manual": "https://www.google.com/search?q={query}+oferta+empleo",
}


def href_looks_usable(href: str | None) -> bool:
    raw = (href or "").strip()
    if not raw or raw.startswith(("#", "javascript:", "mailto:", "tel:", "data:")):
        return False
    lowered = raw.lower()
    if "example.com" in lowered or "example.org" in lowered or "example.net" in lowered:
        return False
    return True


def is_dummy_job_url(url: str | None) -> bool:
    raw = (url or "").strip()
    if not raw:
        return True
    if not href_looks_usable(raw):
        return True
    try:
        parsed = urlparse(raw)
    except Exception:
        return True
    if parsed.scheme and parsed.scheme not in ("http", "https"):
        return True
    host = (parsed.hostname or "").lower()
    if not host:
        return True
    if host in DUMMY_HOSTS or host.endswith(".example.com"):
        return True
    return False


def portal_search_url(source_key: str = "", query: str = "", location: str = "") -> str:
    q = (query or "empleo").strip()[:140]
    loc = (location or "España").strip()[:80]
    template = ""
    try:
        from app.services.portal_catalog import all_portal_definitions

        for item in all_portal_definitions():
            if item.get("key") == source_key:
                template = str((item.get("config") or {}).get("search_url_template") or "")
                break
    except Exception:
        template = ""
    if not template:
        template = _FALLBACK_TEMPLATES.get(source_key or "", _FALLBACK_TEMPLATES["manual"])
    return (
        template.replace("{query}", quote_plus(q))
        .replace("{location}", quote_plus(loc))
        .replace("{qlen}", str(len(q)))
    )


def resolve_job_url(
    url: str | None,
    *,
    source: str = "",
    title: str = "",
    location: str = "",
) -> tuple[str, dict[str, Any]]:
    """Devuelve (url usable, meta). Si la original es dummy, busca en el portal."""
    raw = (url or "").strip()
    if not is_dummy_job_url(raw):
        parsed = urlparse(raw)
        path = (parsed.path or "").lower()
        query = (parsed.query or "").lower()
        is_search = any(
            token in path or token in query
            for token in ("/jobs?", "jobsearch", "search-results", "/search", "ofertas-trabajo")
        )
        return raw, {"openable": True, "is_search": is_search, "repaired": False}

    fallback = portal_search_url(source, title or "empleo", location)
    return fallback, {"openable": True, "is_search": True, "repaired": True}


def repair_dummy_job_urls(db) -> int:
    """Reescribe en BD las ofertas con example.com / vacías. Devuelve cuántas tocó."""
    from app.models import Job

    changed = 0
    rows = db.query(Job).all()
    for job in rows:
        resolved, meta = resolve_job_url(
            job.url, source=job.source or "", title=job.title or "", location=job.location or ""
        )
        if meta.get("repaired") and resolved != (job.url or ""):
            job.url = resolved
            changed += 1
    if changed:
        db.commit()
    return changed
