from __future__ import annotations

from datetime import datetime, timezone
from typing import Any

import httpx

from app.scrapers.base import BaseScraper, JobDTO


class RemoteOKScraper(BaseScraper):
    key = "remoteok"
    name = "RemoteOK"

    def fetch(self) -> list[JobDTO]:
        url = "https://remoteok.com/api"
        headers = {"User-Agent": self.user_agent, "Accept": "application/json"}
        with httpx.Client(timeout=45.0, headers=headers, follow_redirects=True) as client:
            resp = client.get(url)
            resp.raise_for_status()
            data = resp.json()

        jobs: list[JobDTO] = []
        tag_filter = (self.config.get("tag") or "").lower()
        for item in data:
            if not isinstance(item, dict) or "id" not in item or "position" not in item:
                continue
            tags = [str(t).lower() for t in (item.get("tags") or [])]
            if tag_filter and tag_filter not in tags and tag_filter not in (item.get("position") or "").lower():
                # keep broad IT: skip only if tag configured and clearly unrelated — still include all by default
                pass
            desc = item.get("description") or ""
            location = item.get("location") or "Remote"
            salary_min = item.get("salary_min") or None
            salary_max = item.get("salary_max") or None
            if isinstance(salary_min, str):
                salary_min = None
            if isinstance(salary_max, str):
                salary_max = None
            if not salary_min:
                smin, smax, scur = self.parse_salary_usd(f"{item.get('position','')} {desc}")
                salary_min, salary_max = smin, smax
                currency = scur
            else:
                currency = "USD"
            posted = None
            if item.get("date"):
                try:
                    posted = datetime.fromisoformat(str(item["date"]).replace("Z", "+00:00"))
                except ValueError:
                    posted = None
            slug = item.get("slug") or item.get("id")
            job_url = item.get("url") or f"https://remoteok.com/remote-jobs/{slug}"
            jobs.append(
                JobDTO(
                    external_id=str(item["id"]),
                    source=self.key,
                    title=item.get("position") or "Untitled",
                    company=item.get("company") or "",
                    location=location,
                    remote=True,
                    salary_min=int(salary_min) if salary_min else None,
                    salary_max=int(salary_max) if salary_max else None,
                    salary_currency=currency,
                    url=job_url,
                    description=desc,
                    lang=self.detect_lang(desc),
                    tags=tags,
                    requires_english_fluent=self.detect_english_fluent(desc),
                    hire_from_spain_ok=True,
                    posted_at=posted,
                    raw=item if isinstance(item, dict) else {},
                )
            )
        return jobs


class RemotiveScraper(BaseScraper):
    key = "remotive"
    name = "Remotive"

    def fetch(self) -> list[JobDTO]:
        # Vacío = feed amplio (cualquier sector); si hay category, filtrar
        category = (self.config.get("category") or "").strip()
        url = "https://remotive.com/api/remote-jobs"
        if category:
            url = f"{url}?category={category}"
        headers = {"User-Agent": self.user_agent}
        with httpx.Client(timeout=45.0, headers=headers, follow_redirects=True) as client:
            resp = client.get(url)
            resp.raise_for_status()
            payload = resp.json()

        jobs: list[JobDTO] = []
        for item in payload.get("jobs", []):
            desc = item.get("description") or ""
            smin, smax, scur = self.parse_salary_usd(desc + " " + (item.get("salary") or ""))
            posted = None
            if item.get("publication_date"):
                try:
                    posted = datetime.fromisoformat(str(item["publication_date"]).replace("Z", "+00:00"))
                except ValueError:
                    posted = datetime.now(timezone.utc)
            jobs.append(
                JobDTO(
                    external_id=str(item.get("id")),
                    source=self.key,
                    title=item.get("title") or "Untitled",
                    company=item.get("company_name") or "",
                    location=item.get("candidate_required_location") or "Remote",
                    remote=True,
                    salary_min=smin,
                    salary_max=smax,
                    salary_currency=scur,
                    url=item.get("url") or "",
                    description=desc,
                    lang=self.detect_lang(desc),
                    tags=[str(t).lower() for t in (item.get("tags") or [])],
                    requires_english_fluent=self.detect_english_fluent(desc),
                    hire_from_spain_ok=None,
                    posted_at=posted,
                    raw=item,
                )
            )
        return jobs


class ArbeitnowScraper(BaseScraper):
    key = "arbeitnow"
    name = "Arbeitnow"

    def fetch(self) -> list[JobDTO]:
        url = "https://www.arbeitnow.com/api/job-board-api"
        headers = {"User-Agent": self.user_agent}
        with httpx.Client(timeout=45.0, headers=headers, follow_redirects=True) as client:
            resp = client.get(url)
            resp.raise_for_status()
            payload = resp.json()

        jobs: list[JobDTO] = []
        for item in payload.get("data", []):
            desc = item.get("description") or ""
            tags = [str(t).lower() for t in (item.get("tags") or [])]
            remote = bool(item.get("remote")) or self.detect_remote(desc, item.get("location") or "")
            smin, smax, scur = self.parse_salary_usd(desc)
            jobs.append(
                JobDTO(
                    external_id=str(item.get("slug") or item.get("url")),
                    source=self.key,
                    title=item.get("title") or "Untitled",
                    company=item.get("company_name") or "",
                    location=item.get("location") or "",
                    remote=remote,
                    salary_min=smin,
                    salary_max=smax,
                    salary_currency=scur,
                    url=item.get("url") or "",
                    description=desc,
                    lang=self.detect_lang(desc),
                    tags=tags,
                    requires_english_fluent=self.detect_english_fluent(desc),
                    hire_from_spain_ok=None,
                    posted_at=None,
                    raw=item,
                )
            )
        return jobs
