from __future__ import annotations

import re
import urllib.parse
from pathlib import Path
from typing import List, Optional

from ..models import JobDescription
from .base import JobSource


class LinkedInJobSource(JobSource):
    """
    Authenticated LinkedIn job search source.

    This is best-effort because LinkedIn's DOM changes frequently.
    """

    def __init__(
        self,
        *,
        storage_state: Path,
        headless: bool = False,
    ) -> None:
        self.storage_state = storage_state
        self.headless = headless

    def search(self, *, query: str, max_jobs: int) -> List[JobDescription]:
        from playwright.sync_api import sync_playwright

        if not self.storage_state.exists():
            raise FileNotFoundError(f"storage_state not found: {self.storage_state}")

        keywords = urllib.parse.quote(query.strip())
        search_url = f"https://www.linkedin.com/jobs/search/?keywords={keywords}"

        with sync_playwright() as p:
            browser = p.chromium.launch(headless=self.headless)
            context = browser.new_context(storage_state=str(self.storage_state))
            page = context.new_page()

            page.goto(search_url, wait_until="domcontentloaded")

            # Collect job links from current results page.
            anchors = page.locator('a[href*="/jobs/view/"]')
            seen = set()
            job_links: List[str] = []

            for i in range(min(300, anchors.count())):
                a = anchors.nth(i)
                try:
                    href = a.get_attribute("href") or ""
                    if not href or "/jobs/view/" not in href:
                        continue
                    url = href if href.startswith("http") else "https://www.linkedin.com" + href
                    if url in seen:
                        continue
                    seen.add(url)
                    job_links.append(url)
                    if len(job_links) >= max_jobs:
                        break
                except Exception:
                    continue

            results: List[JobDescription] = []
            for job_url in job_links:
                page.goto(job_url, wait_until="domcontentloaded")
                # Best-effort extraction: title + main text content.
                title = ""
                try:
                    h1 = page.locator("h1").first
                    if h1.count() > 0:
                        title = (h1.inner_text() or "").strip()
                except Exception:
                    title = ""

                main = ""
                try:
                    main = page.locator("main").inner_text()
                except Exception:
                    main = ""

                # Remove excessive whitespace.
                cleaned = re.sub(r"\s+", " ", (main or "")).strip()
                raw_text = (title + "\n\n" + cleaned).strip()

                results.append(
                    JobDescription(
                        raw_text=raw_text,
                        title=title or "LinkedIn Job",
                        url=job_url,
                        company=None,
                        location=None,
                    )
                )

            context.close()
            browser.close()

            return results

