"""Issuer Sync: populate issuer_master / symbol_master from Oracle company info."""
from __future__ import annotations

import argparse
import asyncio
import datetime as dt
import uuid

from sqlalchemy.dialects.postgresql import insert

from libs.common.config import get_settings
from libs.common.ids import issuer_id_from_cik, new_job_run_id, symbol_id_from_ticker
from libs.common.logging import bind_job_run_id, configure_logging, get_logger
from libs.db.models import IssuerMaster, JobRun, SymbolMaster
from libs.db.session import get_session
from libs.oracle_client import FinancialService, make_oracle_client

logger = get_logger(__name__)


async def run_issuer_sync(run_id: str) -> dict[str, int]:
    settings = get_settings()
    symbols = settings.get_symbols()
    stats = {"seen": 0, "written": 0, "errors": 0}

    async with make_oracle_client() as client:
        svc = FinancialService(client)

        async with get_session() as session:
            job = JobRun(
                job_run_id=uuid.UUID(run_id),
                job_name="issuer_sync",
                source_name="oracle",
                run_date=dt.date.today(),
                status="running",
            )
            session.add(job)
            await session.flush()

            for ticker in symbols:
                stats["seen"] += 1
                try:
                    info = await svc.get_company_info(ticker)

                    cik = info.cik
                    issuer_id_str = issuer_id_from_cik(cik) if cik else f"ISSUER::{ticker}"
                    symbol_id_str = symbol_id_from_ticker(ticker, info.exchange or "US")

                    # Upsert issuer
                    issuer_stmt = (
                        insert(IssuerMaster)
                        .values(
                            issuer_id=issuer_id_str,
                            cik=cik,
                            ticker=ticker,
                            issuer_name=info.name or ticker,
                            exchange=info.exchange,
                            country_code=info.country,
                            is_active=True,
                            created_at_utc=dt.datetime.now(tz=dt.UTC),
                            updated_at_utc=dt.datetime.now(tz=dt.UTC),
                        )
                        .on_conflict_do_update(
                            index_elements=["issuer_id"],
                            set_={
                                "ticker": ticker,
                                "issuer_name": info.name or ticker,
                                "exchange": info.exchange,
                                "updated_at_utc": dt.datetime.now(tz=dt.UTC),
                            },
                        )
                    )
                    await session.execute(issuer_stmt)

                    # Upsert symbol
                    symbol_stmt = (
                        insert(SymbolMaster)
                        .values(
                            symbol_id=symbol_id_str,
                            issuer_id=issuer_id_str,
                            ticker=ticker,
                            venue=info.exchange or "US",
                            asset_type="common_stock",
                            currency="USD",
                            is_primary=True,
                            created_at_utc=dt.datetime.now(tz=dt.UTC),
                            updated_at_utc=dt.datetime.now(tz=dt.UTC),
                        )
                        .on_conflict_do_update(
                            index_elements=["symbol_id"],
                            set_={
                                "ticker": ticker,
                                "updated_at_utc": dt.datetime.now(tz=dt.UTC),
                            },
                        )
                    )
                    await session.execute(symbol_stmt)

                    stats["written"] += 1
                    logger.info("issuer_synced", ticker=ticker, issuer_id=issuer_id_str)

                except Exception as exc:
                    logger.error("issuer_sync_error", ticker=ticker, error=str(exc))
                    stats["errors"] += 1

            job.status = "succeeded" if stats["errors"] == 0 else "partial"
            job.finished_at_utc = dt.datetime.now(tz=dt.UTC)
            job.records_seen = stats["seen"]
            job.records_written = stats["written"]
            job.error_count = stats["errors"]

    logger.info("issuer_sync_done", **stats)
    return stats


def main() -> None:
    parser = argparse.ArgumentParser(description="Issuer Sync")
    parser.add_argument("--run-id", default=new_job_run_id())
    args = parser.parse_args()

    settings = get_settings()
    configure_logging(settings.log_level)
    bind_job_run_id(args.run_id)

    asyncio.run(run_issuer_sync(args.run_id))


if __name__ == "__main__":
    main()
