"""The ETL seam: walk the strategy registry, read each present *_state.json via the state_reader, compute
the gate, and upsert (rows + summary) into the cockpit DB. Best-effort per tracker — one bad file is logged
and skipped, never aborting the batch (a single broken tracker must not blind the whole cockpit)."""
from __future__ import annotations

import datetime as dt
import logging
from pathlib import Path

from fxhnt.adapters.persistence.forward_nav import ForwardNavRepo
from fxhnt.adapters.persistence.state_reader import ForwardStateReader
from fxhnt.application.gate import evaluate_gate
from fxhnt.registry import STRATEGY_REGISTRY

_log = logging.getLogger(__name__)


class ForwardIngestService:
    def __init__(self, repo: ForwardNavRepo, state_dir: str,
                 reader: ForwardStateReader | None = None) -> None:
        self._repo = repo
        self._dir = Path(state_dir)
        self._reader = reader or ForwardStateReader()

    def ingest(self, at: dt.datetime) -> int:
        count = 0
        for sid, entry in STRATEGY_REGISTRY.items():
            path = self._dir / f"{entry['state_file']}.json"
            if not path.exists():
                continue
            try:
                summary, rows = self._reader.read(path, sid)
            except (ValueError, KeyError, OSError) as e:
                _log.warning("skipping tracker %s: %s", sid, e)
                continue
            verdict = evaluate_gate(summary, entry["gate_spec"])
            self._repo.upsert_rows(rows, at)
            self._repo.upsert_summary(summary, verdict.status, verdict.reason, at)
            count += 1
        return count


def ingest_forward_state(dsn: str, state_dir: str) -> None:
    """Normalize every present tracker state file and upsert rows + summary into the cockpit DB.

    Reusable entry-point called by both the CLI command and the Dagster cockpit_forward asset.
    Idempotent: migrate() is a no-op if tables already exist.
    """
    repo = ForwardNavRepo(dsn)
    repo.migrate()
    n = ForwardIngestService(repo, state_dir).ingest(at=dt.datetime.now(dt.timezone.utc).replace(tzinfo=None))
    _log.info("ingest_forward_state: ingested %d tracker(s) from %s", n, state_dir)
