from __future__ import annotations

import re
from dataclasses import dataclass
from typing import Any
from urllib.parse import urlparse

from app.core.config import get_settings
from app.models import Job, Profile, User


@dataclass
class AdapterPlan:
    adapter: str
    mode: str  # assisted | semi_auto
    checklist: list[str]
    prefill: dict[str, Any]


def detect_adapter(url: str) -> str:
    host = urlparse(url).netloc.lower()
    path = urlparse(url).path.lower()
    blob = f"{host}{path}"
    if "greenhouse.io" in host or "boards.greenhouse" in host:
        return "greenhouse"
    if "lever.co" in host or "jobs.lever.co" in host:
        return "lever"
    if "myworkdayjobs.com" in host or "workday" in blob:
        return "workday"
    if "infojobs" in host:
        return "infojobs"
    if "indeed." in host:
        return "indeed"
    if "linkedin." in host:
        return "linkedin"
    if "remoteok" in host:
        return "remoteok"
    return "generic"


def build_prefill(user: User, profile: Profile | None) -> dict[str, Any]:
    profile = profile or user.profile
    name_parts = (user.name or "").split(" ", 1)
    return {
        "full_name": user.name,
        "first_name": name_parts[0] if name_parts else "",
        "last_name": name_parts[1] if len(name_parts) > 1 else "",
        "email": user.email,
        "phone": (profile.phone if profile else "") or "",
        "linkedin": (profile.linkedin_url if profile else "") or "",
        "portfolio": (profile.portfolio_url if profile else "") or "",
        "location": (profile.location if profile else "") or "Spain",
        "work_authorization": (profile.work_authorization if profile else "") or "",
    }


def prepare_apply(user: User, job: Job, cv_md: str | None = None, cover: str | None = None) -> AdapterPlan:
    adapter = detect_adapter(job.url)
    prefill = build_prefill(user, user.profile)
    checklist = [
        "Revisa el CV adaptado / carta",
        "Abre la oferta en el navegador",
        "Pega o adjunta el CV",
        "Completa campos personales",
        "Revisa y envía manualmente (recomendado)",
    ]
    if adapter in {"greenhouse", "lever"}:
        mode = "semi_auto"
        checklist.insert(0, "JobsWorld puede rellenar el formulario ATS y pausar antes de enviar")
    else:
        mode = "assisted"
        if adapter == "linkedin":
            checklist.append("LinkedIn: aplica Easy Apply manualmente (sin bot)")
        if adapter in {"indeed", "infojobs"}:
            checklist.append("Portal con anti-bot: usa modo asistido")
    if cv_md:
        prefill["cv_markdown"] = cv_md
    if cover:
        prefill["cover_letter"] = cover
    return AdapterPlan(adapter=adapter, mode=mode, checklist=checklist, prefill=prefill)


def run_semi_auto_fill(job: Job, prefill: dict[str, Any], confirm_submit: bool = False) -> dict[str, Any]:
    """Fill known ATS forms with Playwright; never submit unless confirm_submit and global flag."""
    settings = get_settings()
    log: list[str] = []
    adapter = detect_adapter(job.url)

    try:
        from playwright.sync_api import sync_playwright
    except Exception as exc:  # noqa: BLE001
        return {
            "status": "error",
            "adapter": adapter,
            "message": f"Playwright no disponible: {exc}. Usa modo asistido.",
            "log": log,
        }

    auto = bool(confirm_submit and settings.apply_auto_submit)
    screenshot_path = None

    try:
        with sync_playwright() as p:
            browser = p.chromium.launch(headless=settings.playwright_headless)
            page = browser.new_page()
            page.goto(job.url, wait_until="domcontentloaded", timeout=60000)
            log.append(f"Abierto {job.url}")

            def fill_first(selectors: list[str], value: str, label: str) -> None:
                if not value:
                    return
                for sel in selectors:
                    loc = page.locator(sel).first
                    if loc.count() and loc.is_visible():
                        loc.fill(value)
                        log.append(f"Rellenado {label} via {sel}")
                        return

            fill_first(
                ['input[name="job_application[first_name]"]', 'input[name="first_name"]', "#first_name", 'input[autocomplete="given-name"]'],
                prefill.get("first_name", ""),
                "nombre",
            )
            fill_first(
                ['input[name="job_application[last_name]"]', 'input[name="last_name"]', "#last_name", 'input[autocomplete="family-name"]'],
                prefill.get("last_name", ""),
                "apellidos",
            )
            fill_first(
                ['input[name="job_application[email]"]', 'input[type="email"]', "#email", 'input[autocomplete="email"]'],
                prefill.get("email", ""),
                "email",
            )
            fill_first(
                ['input[name="job_application[phone]"]', 'input[type="tel"]', "#phone", 'input[autocomplete="tel"]'],
                prefill.get("phone", ""),
                "teléfono",
            )
            fill_first(
                ['input[name*="linkedin"]', 'input[id*="linkedin"]'],
                prefill.get("linkedin", ""),
                "linkedin",
            )

            cover = prefill.get("cover_letter") or ""
            if cover:
                fill_first(
                    ["textarea", 'textarea[name*="cover"]', "#cover_letter"],
                    cover[:8000],
                    "carta",
                )

            out_dir = settings.data_dir / "exports"
            out_dir.mkdir(parents=True, exist_ok=True)
            screenshot_path = str(out_dir / f"apply_{job.id}.png")
            page.screenshot(path=screenshot_path, full_page=True)
            log.append(f"Screenshot: {screenshot_path}")

            if auto:
                # Best-effort submit — only if explicitly enabled
                for sel in ['button[type="submit"]', 'input[type="submit"]', "button:has-text('Submit')"]:
                    btn = page.locator(sel).first
                    if btn.count() and btn.is_visible():
                        btn.click()
                        log.append(f"Submit click via {sel}")
                        break
                status = "submitted"
                message = "Formulario enviado (auto-submit activo)."
            else:
                status = "filled_pending_review"
                message = "Formulario rellenado. Revisa en el navegador y envía tú."
                # Keep browser open briefly if not headless
                if not settings.playwright_headless:
                    page.wait_for_timeout(1500)

            browser.close()
            return {
                "status": status,
                "adapter": adapter,
                "message": message,
                "log": log,
                "screenshot_path": screenshot_path,
            }
    except Exception as exc:  # noqa: BLE001
        return {
            "status": "error",
            "adapter": adapter,
            "message": str(exc),
            "log": log + [str(exc)],
            "screenshot_path": screenshot_path,
        }


def strip_html(text: str) -> str:
    return re.sub(r"<[^>]+>", " ", text or "")
