"""Retrieves security data from SEC EDGAR using the edgartools package."""

__author__ = "Jerome Lecomte"
__license__ = "MIT"

import contextlib
import typing as t

import edgar

import finquotes as fq

SOURCE = "finquotes.edgartools"

# Maps edgartools exchange names to ISO 10383 MIC codes.
_EXCHANGE_TO_MIC: dict[str, str] = {
    "Nasdaq": "XNAS",
    "NYSE": "XNYS",
    "NYSE MKT": "XASE",
    "NYSE ARCA": "ARCX",
    "OTC": "XOTC",
}


class EdgartoolsSecurityFeed(fq.NetworkConfigMixin, fq.AbstractSecurityFeed):
    """Retrieves security metadata from SEC EDGAR via the edgartools package."""

    def __init__(self: t.Self, **kwargs: t.Any) -> None:
        super().__init__(name=__name__, source=SOURCE, **kwargs)
        identity = self._api_key
        with contextlib.suppress(KeyError):
            identity = fq.get_api_key(SOURCE)
        if identity:
            edgar.set_identity(identity)

    def fetch_securities(
        self: t.Self,
        symbols: t.Iterable[str],
    ) -> t.Generator[fq.Security, None, None]:
        """Fetch security info from SEC EDGAR for each symbol."""
        for symbol in symbols:
            try:
                yield self._fetch_security(symbol)
            except edgar.CompanyNotFoundError as err:
                fq.log.warning("failed to fetch %s: %s", symbol, err)

    def _fetch_security(self: t.Self, symbol: str) -> fq.Security:
        company = edgar.Company(symbol)
        address = company.mailing_address()
        exchanges = company.get_exchanges()
        mic = _EXCHANGE_TO_MIC.get(exchanges[0]) if exchanges else None
        # CIK inputs (all digits) are resolved to a ticker when possible.
        resolved_symbol = company.get_ticker() or symbol if symbol.isdigit() else symbol

        return fq.Security(
            symbol=resolved_symbol,
            name=company.name,
            cik=str(company.cik) if company.cik is not None else None,
            sic=int(company.sic) if company.sic else None,
            industry=company.industry or None,
            exchange=fq.Exchange(mic) if mic else None,
            city=address.city or None,
            state=address.state_or_country or None,
            source=self.source,
        )


def build_security_feed(*args: t.Any, **kwargs: t.Any) -> EdgartoolsSecurityFeed:
    """Build an edgartools security feed."""
    return EdgartoolsSecurityFeed(*args, **kwargs)
