from __future__ import annotations

from typing import Any, Dict, List, Optional

import httpx

VALID_SOURCES = [
    "reddit", "twitter", "hackernews", "telegram",
    "linkedin_jobs", "linkedin_people", "producthunt", "indiehackers",
    "devto", "lobsters", "hashnode", "betalist", "echojs", "wip",
    "launchingnext", "hackernoon", "makerlog", "alternativeto",
    "saashub", "tldr", "changelog", "google_news",
]


class AiASIntelligenceError(Exception):
    def __init__(self, status: int, detail: str):
        super().__init__(f"AiAS Intelligence API error {status}: {detail}")
        self.status = status
        self.detail = detail


class AiASIntelligence:
    def __init__(
        self,
        api_key: str,
        base_url: str = "https://aiassist.net",
        timeout: float = 60.0,
    ):
        if not api_key:
            raise ValueError("api_key is required")
        self._base = base_url.rstrip("/") + "/v1/intelligence"
        self._headers = {
            "Authorization": f"Bearer {api_key}",
            "Content-Type": "application/json",
        }
        self._timeout = timeout
        self._client = httpx.Client(timeout=self._timeout)

    def _handle(self, resp: httpx.Response) -> Dict[str, Any]:
        if resp.status_code >= 400:
            detail = resp.text
            try:
                detail = resp.json().get("detail", detail)
            except Exception:
                pass
            raise AiASIntelligenceError(resp.status_code, detail)
        return resp.json()

    def sources(self) -> Dict[str, Any]:
        resp = self._client.get(f"{self._base}/sources", headers=self._headers)
        return self._handle(resp)

    def scan(
        self,
        sources: List[str],
        keywords: Optional[List[str]] = None,
        limit: int = 25,
        category: str = "recent",
        subreddits: Optional[List[str]] = None,
    ) -> Dict[str, Any]:
        resp = self._client.post(
            f"{self._base}/scan",
            headers=self._headers,
            json={
                "sources": sources,
                "keywords": keywords or [],
                "limit": limit,
                "category": category,
                "subreddits": subreddits or [],
            },
        )
        return self._handle(resp)

    def extract_keywords(
        self,
        prompt: str,
        existing_keywords: Optional[List[str]] = None,
        model: Optional[str] = None,
        provider: Optional[str] = None,
    ) -> Dict[str, Any]:
        resp = self._client.post(
            f"{self._base}/extract-keywords",
            headers=self._headers,
            json={
                "prompt": prompt,
                "existing_keywords": existing_keywords or [],
                "model": model,
                "provider": provider,
            },
        )
        return self._handle(resp)

    def close(self):
        self._client.close()

    def __enter__(self):
        return self

    def __exit__(self, *args):
        self.close()


class AiASIntelligenceAsync:
    def __init__(
        self,
        api_key: str,
        base_url: str = "https://aiassist.net",
        timeout: float = 60.0,
    ):
        if not api_key:
            raise ValueError("api_key is required")
        self._base = base_url.rstrip("/") + "/v1/intelligence"
        self._headers = {
            "Authorization": f"Bearer {api_key}",
            "Content-Type": "application/json",
        }
        self._timeout = timeout
        self._client = httpx.AsyncClient(timeout=self._timeout)

    async def _handle(self, resp: httpx.Response) -> Dict[str, Any]:
        if resp.status_code >= 400:
            detail = resp.text
            try:
                detail = resp.json().get("detail", detail)
            except Exception:
                pass
            raise AiASIntelligenceError(resp.status_code, detail)
        return resp.json()

    async def sources(self) -> Dict[str, Any]:
        resp = await self._client.get(f"{self._base}/sources", headers=self._headers)
        return await self._handle(resp)

    async def scan(
        self,
        sources: List[str],
        keywords: Optional[List[str]] = None,
        limit: int = 25,
        category: str = "recent",
        subreddits: Optional[List[str]] = None,
    ) -> Dict[str, Any]:
        resp = await self._client.post(
            f"{self._base}/scan",
            headers=self._headers,
            json={
                "sources": sources,
                "keywords": keywords or [],
                "limit": limit,
                "category": category,
                "subreddits": subreddits or [],
            },
        )
        return await self._handle(resp)

    async def extract_keywords(
        self,
        prompt: str,
        existing_keywords: Optional[List[str]] = None,
        model: Optional[str] = None,
        provider: Optional[str] = None,
    ) -> Dict[str, Any]:
        resp = await self._client.post(
            f"{self._base}/extract-keywords",
            headers=self._headers,
            json={
                "prompt": prompt,
                "existing_keywords": existing_keywords or [],
                "model": model,
                "provider": provider,
            },
        )
        return await self._handle(resp)

    async def close(self):
        await self._client.aclose()

    async def __aenter__(self):
        return self

    async def __aexit__(self, *args):
        await self.close()
