"""Filing-related Oracle service methods."""

from __future__ import annotations

import re

from libs.oracle_client.client import OracleClient
from libs.oracle_client.models import (
    ExhibitDocument,
    ExhibitResponse,
    FilingDocumentsResponse,
    FilingEntry,
    FilingSearchResponse,
)

# Mapping from SGML ITEM INFORMATION descriptions to SEC 8-K item numbers.
_ITEM_DESC_TO_NUMBER: dict[str, str] = {
    "entry into a material definitive agreement": "1.01",
    "termination of a material definitive agreement": "1.02",
    "bankruptcy or receivership": "1.03",
    "mine safety": "1.04",
    "completion of acquisition or disposition of assets": "2.01",
    "results of operations and financial condition": "2.02",
    "creation of a direct financial obligation": "2.03",
    "triggering events that accelerate": "2.04",
    "costs associated with exit or disposal": "2.05",
    "material impairments": "2.06",
    "notice of delisting": "3.01",
    "unregistered sales of equity securities": "3.02",
    "material modification to rights": "3.03",
    r"changes in registrant.s certifying accountant": "4.01",
    "non-reliance on previously issued": "4.02",
    "changes in control of registrant": "5.01",
    "departure of directors or certain officers": "5.02",
    "amendments to articles of incorporation or bylaws": "5.03",
    "temporary suspension of trading": "5.04",
    r"amendments to the registrant.s code of ethics": "5.05",
    "change in shell company status": "5.06",
    "submission of matters to a vote": "5.07",
    "shareholder nominations": "5.08",
    "regulation fd disclosure": "7.01",
    "other events": "8.01",
    "financial statements and exhibits": "9.01",
}


def extract_items_from_sgml_header(content: str) -> list[str]:
    """Extract SEC 8-K item numbers from SGML header ITEM INFORMATION fields."""
    items_found: list[str] = []
    matches = re.findall(r"ITEM INFORMATION:\s*(.+)", content)
    for desc in matches:
        desc_lower = desc.strip().lower()
        for key, item_num in _ITEM_DESC_TO_NUMBER.items():
            if re.search(key, desc_lower):
                items_found.append(item_num)
                break
    return list(dict.fromkeys(items_found))


class FilingsService:
    def __init__(self, client: OracleClient) -> None:
        self._client = client

    async def search_filings(
        self,
        ticker: str,
        form_type: str | None = None,
        start_date: str | None = None,
        end_date: str | None = None,
    ) -> FilingSearchResponse:
        params: dict[str, str] = {}
        if form_type:
            params["form_type"] = form_type
        if start_date:
            params["start_date"] = start_date
        if end_date:
            params["end_date"] = end_date
        data = await self._client.get(f"/api/v1/filings/search/{ticker}", params=params)
        # Real Oracle: {"ticker": ..., "filings": [{accession_number, form_type, ...}], "total_count": ...}
        filings = [
            FilingEntry(
                accession_no=f["accession_number"],
                form_type=f["form_type"],
                filing_date=f["filing_date"],
                accepted_at=f.get("accepted_at"),
                primary_document=f.get("primary_document"),
                description=f.get("filing_description"),
                items=f.get("items", []),
            )
            for f in data.get("filings", [])
        ]
        return FilingSearchResponse(
            ticker=data.get("ticker", ticker),
            filings=filings,
            total=data.get("total_count", len(filings)),
        )

    async def get_documents(self, accession_no: str) -> FilingDocumentsResponse:
        data = await self._client.get(f"/api/v1/filings/documents/{accession_no}")
        exhibits = [ExhibitDocument.model_validate(e) for e in data.get("exhibits", [])]
        return FilingDocumentsResponse(
            accession_no=data.get("accession_number", accession_no),
            exhibits=exhibits,
        )

    async def get_exhibit(
        self, accession_no: str, exhibit_type: str = "EX-99.1"
    ) -> ExhibitResponse:
        params = {"exhibit_type": exhibit_type}
        data = await self._client.get(f"/api/v1/filings/exhibit/{accession_no}", params=params)
        # Real Oracle: {"accession_number": ..., "exhibit_type": ..., "content": ...}
        return ExhibitResponse(
            accession_no=data.get("accession_number", accession_no),
            exhibit_type=data.get("exhibit_type", exhibit_type),
            content=data.get("content", ""),
        )

    async def get_filing_items(self, accession_no: str) -> list[str]:
        """Extract SEC 8-K item numbers from the complete submission text.

        Fetches the full submission text (exhibit_type="") which contains the
        SGML header with ITEM INFORMATION fields, then parses item numbers.
        """
        try:
            data = await self._client.get(
                f"/api/v1/filings/exhibit/{accession_no}", params={"exhibit_type": ""}
            )
            content = data.get("content", "")
            if not content:
                return []
            return extract_items_from_sgml_header(content)
        except Exception:
            return []
