"""Scraper panoramafirm.pl — wyszukiwarka firm.

Robots.txt zezwala na pełen scraping. Wyniki są generowane server-side,
więc proste GET-y wystarczą.
"""

from __future__ import annotations

import logging
import re
from typing import Iterator

from bs4 import BeautifulSoup

from .base import Lead, ScraperSource

log = logging.getLogger(__name__)

BASE = "https://panoramafirm.pl"
SEARCH_URL = f"{BASE}/szukaj"
DEFAULT_QUERIES = [
    "kancelaria adwokacka prawo rodzinne",
    "adwokat rozwód",
    "kancelaria prawo rodzinne",
]


class PanoramafirmScraper(ScraperSource):
    name = "panoramafirm"

    def __init__(
        self,
        limit: int | None = None,
        queries: list[str] | None = None,
        max_pages: int = 5,
    ):
        super().__init__(limit=limit)
        self.queries = queries or DEFAULT_QUERIES
        self.max_pages = max_pages

    def _fetch_page(self, query: str, page: int) -> list[Lead]:
        params = {"k": query}
        if page > 1:
            params["page"] = page
        r = self.get(SEARCH_URL, params=params)
        if r is None:
            return []
        soup = BeautifulSoup(r.text, "lxml")
        leads: list[Lead] = []

        for h2 in soup.find_all("h2", class_="text-h1"):
            # Szukaj najmniejszego ancestor div, który zawiera email lub telefon.
            card = h2
            text = ""
            for _ in range(8):
                card = card.parent
                if card is None:
                    break
                text = card.get_text(" ", strip=True)
                if "@" in text or re.search(r"\d{3}[\s\-]?\d{3}[\s\-]?\d{3}", text):
                    break
            if card is None or not text:
                continue
            name = h2.get_text(" ", strip=True)
            email = self.extract_email(text)
            phone = self.extract_phone(text)

            # Filtruj — tylko prawnicze
            if not re.search(r"adwokat|radca|kancelaria|prawnik|prawo", name, re.I):
                continue

            # Adres — wyłap "ul./al. ... 00-000 Miasto"
            street = postal = city = None
            am = re.search(
                r"(ul\.|al\.|aleja|os\.|pl\.)\s+([^,]+?),\s*(\d{2}-\d{3})\s+([\w\sĄąĆćĘęŁłŃńÓóŚśŹźŻż\-]+?)(?:\s|$)",
                text,
                re.I,
            )
            if am:
                street = f"{am.group(1)} {am.group(2)}".strip()
                postal = am.group(3)
                city = am.group(4).strip()

            lead = Lead(
                name=name,
                source=self.name,
                nameMore="Kancelaria / prawo rodzinne",
                city=city,
                street=street,
                postalCode=postal,
                email=email,
                phone=phone,
            )
            leads.append(lead)
        return leads

    def fetch(self) -> Iterator[Lead]:
        yielded = 0
        seen_keys: set[tuple[str, str]] = set()
        for query in self.queries:
            for page in range(1, self.max_pages + 1):
                if self.limit and yielded >= self.limit:
                    return
                log.info("[panoramafirm] query=%r page=%d", query, page)
                leads = self._fetch_page(query, page)
                if not leads:
                    break
                for lead in leads:
                    if self.limit and yielded >= self.limit:
                        return
                    if not lead.is_valid():
                        continue
                    key = (lead.email or "", lead.phone or "")
                    if key in seen_keys:
                        continue
                    seen_keys.add(key)
                    yielded += 1
                    yield lead
