"""
edgar_text.py — Descarga de textos financieros de SEC EDGAR.

Obtiene:
- Earnings press releases (8-K, Exhibit 99.1)
- Lista de 10-Q y 10-K recientes para detectar nuevos filings
"""

from __future__ import annotations

import logging
import re
import time
from typing import Optional

import requests
from bs4 import BeautifulSoup

log = logging.getLogger("edgar_text")

HEADERS = {"User-Agent": "Leonex-Fundamental-Agent research@leonex.local"}
EDGAR_BASE = "https://www.sec.gov"
SUBMISSIONS_URL = "https://data.sec.gov/submissions/CIK{cik}.json"


def _get(url: str, timeout: int = 20) -> requests.Response:
    time.sleep(0.12)
    return requests.get(url, headers=HEADERS, timeout=timeout)


def get_recent_filings(cik: str, form_types: list[str] = None) -> list[dict]:
    """
    Devuelve los filings recientes de una empresa desde EDGAR.
    form_types: ["10-Q", "10-K", "8-K"] — None = todos
    """
    if form_types is None:
        form_types = ["10-Q", "10-K", "8-K"]

    cik_norm = cik.lstrip("0").zfill(10)
    url = SUBMISSIONS_URL.format(cik=cik_norm)
    resp = _get(url)
    resp.raise_for_status()
    data = resp.json()

    filings = data.get("filings", {}).get("recent", {})
    results = []
    for i, form in enumerate(filings.get("form", [])):
        if form in form_types:
            results.append({
                "form": form,
                "filed": filings["filingDate"][i],
                "accession": filings["accessionNumber"][i].replace("-", ""),
                "primary_doc": filings.get("primaryDocument", [""])[i],
                "period": filings.get("reportDate", [""])[i],
            })
    return results


def get_8k_exhibit(cik: str, accession: str) -> Optional[str]:
    """
    Descarga el texto del Exhibit 99.1 de un 8-K (earnings press release).
    Devuelve el texto plano limpio o None si no se encuentra.
    """
    cik_norm = cik.lstrip("0").zfill(10)
    index_url = f"{EDGAR_BASE}/Archives/edgar/data/{int(cik_norm)}/{accession}/{accession}-index.htm"

    try:
        resp = _get(index_url)
        soup = BeautifulSoup(resp.text, "html.parser")

        # Buscar el link al Exhibit 99.1
        exhibit_url = None
        for row in soup.find_all("tr"):
            cells = row.find_all("td")
            if len(cells) >= 3:
                desc = cells[0].get_text(strip=True).lower()
                if "ex-99" in desc or "exhibit 99" in desc or "99.1" in desc:
                    link = cells[-1].find("a")
                    if link and link.get("href"):
                        exhibit_url = EDGAR_BASE + link["href"]
                        break

        if not exhibit_url:
            # Intentar buscando en el filing index JSON
            json_url = f"{EDGAR_BASE}/Archives/edgar/data/{int(cik_norm)}/{accession}/index.json"
            resp2 = _get(json_url)
            if resp2.ok:
                idx = resp2.json()
                for item in idx.get("directory", {}).get("item", []):
                    name = item.get("name", "").lower()
                    if "ex99" in name or "exhibit99" in name or "ex-99" in name:
                        exhibit_url = f"{EDGAR_BASE}/Archives/edgar/data/{int(cik_norm)}/{accession}/{item['name']}"
                        break

        if not exhibit_url:
            log.warning("No se encontró Exhibit 99.1 en accession %s", accession)
            return None

        resp3 = _get(exhibit_url)
        # Limpiar HTML si es necesario
        if "html" in resp3.headers.get("content-type", "").lower():
            soup3 = BeautifulSoup(resp3.text, "html.parser")
            text = soup3.get_text(separator="\n")
        else:
            text = resp3.text

        # Limpiar texto
        text = re.sub(r"\n{3,}", "\n\n", text)
        text = re.sub(r" {2,}", " ", text)
        return text.strip()

    except Exception as exc:
        log.error("Error descargando Exhibit 99.1: %s", exc)
        return None


def get_latest_8k_text(cik: str) -> Optional[dict]:
    """
    Devuelve el texto del earnings release más reciente (8-K con Exhibit 99.1).
    """
    filings = get_recent_filings(cik, form_types=["8-K"])
    if not filings:
        return None

    for filing in filings[:5]:  # intentar los 5 más recientes
        text = get_8k_exhibit(cik, filing["accession"])
        if text and len(text) > 500:
            return {
                "filed": filing["filed"],
                "period": filing["period"],
                "accession": filing["accession"],
                "text": text,
            }
    return None


def get_latest_10q_filing(cik: str) -> Optional[dict]:
    """
    Devuelve metadata del 10-Q más reciente disponible en EDGAR.
    """
    filings = get_recent_filings(cik, form_types=["10-Q"])
    if filings:
        return filings[0]
    return None


def check_new_filing_since(cik: str, since_date: str) -> list[dict]:
    """
    Comprueba si hay filings nuevos (10-Q, 10-K, 8-K) desde una fecha dada.
    since_date: "YYYY-MM-DD"
    """
    filings = get_recent_filings(cik)
    return [f for f in filings if f["filed"] > since_date]
