from __future__ import annotations

import json
from datetime import date, datetime, timezone

from app.models.data_import_run import DataImportRun
from app.models.fundamental_snapshot import FundamentalSnapshot
from app.models.sec_filing_gap import SecFilingGap
from app.models.ticker import Ticker
from app.services import fundamentals_quality_service


async def test_latest_sec_validation_blocks_deferred_and_no_history_ciks(
    db_session,
):
    missing = Ticker(symbol="MISSING", cik="0000000001")
    no_history = Ticker(symbol="NEWREG", cik="0000000002")
    healthy = Ticker(symbol="HEALTHY", cik="0000000003")
    db_session.add_all([missing, no_history, healthy])
    await db_session.flush()
    db_session.add(
        DataImportRun(
            source="sec_facts",
            status="deferred",
            validation_json=json.dumps({
                "missing_xbrl": [{"cik": missing.cik, "accession": "MISSING-Q"}],
                "no_xbrl_filings": [{"cik": no_history.cik}],
            }),
            started_at=datetime.now(timezone.utc),
        )
    )
    await db_session.flush()

    assert await fundamentals_quality_service.blocked_ticker_ids(db_session) == {
        missing.id,
        no_history.id,
    }


async def test_active_gap_is_blocked_until_a_later_filing_supersedes_it(db_session):
    ticker = Ticker(symbol="HIST", cik="0000000043")
    now = datetime.now(timezone.utc)
    db_session.add_all([
        ticker,
        SecFilingGap(
            cik=ticker.cik,
            accession="HIST-Q",
            form="10-Q",
            index_date=date.today().replace(day=1),
            reason="coregistrant_facts_rejected",
            first_seen_at=now,
            last_attempted_at=now,
        ),
    ])
    await db_session.flush()

    assert await fundamentals_quality_service.blocked_ticker_ids(db_session) == {
        ticker.id
    }

    db_session.add(
        FundamentalSnapshot(
            cik=ticker.cik,
            accession="LATER-Q",
            form="10-Q",
            filed_date=date.today(),
            accepted_at=datetime.now(timezone.utc),
            period_end=date.today(),
            fiscal_year=date.today().year,
            fiscal_period="Q2",
        )
    )
    await db_session.flush()

    assert await fundamentals_quality_service.blocked_ticker_ids(db_session) == set()


async def test_gap_without_index_date_uses_first_seen_date_for_supersession(
    db_session,
):
    ticker = Ticker(symbol="DATELESS", cik="0000000045")
    first_seen = datetime(2026, 5, 1, 12, tzinfo=timezone.utc)
    db_session.add_all([
        ticker,
        SecFilingGap(
            cik=ticker.cik,
            accession="DATELESS-Q",
            form="10-Q",
            index_date=None,
            reason="not_in_companyfacts",
            first_seen_at=first_seen,
            last_attempted_at=first_seen,
        ),
    ])
    await db_session.flush()

    assert await fundamentals_quality_service.blocked_ticker_ids(db_session) == {
        ticker.id
    }

    db_session.add(
        FundamentalSnapshot(
            cik=ticker.cik,
            accession="LATER-DATELESS-Q",
            form="10-Q",
            filed_date=date(2026, 5, 2),
            accepted_at=datetime(2026, 5, 2, 12, tzinfo=timezone.utc),
            period_end=date(2026, 3, 31),
            fiscal_year=2026,
            fiscal_period="Q1",
        )
    )
    await db_session.flush()

    assert await fundamentals_quality_service.blocked_ticker_ids(db_session) == set()


async def test_ticker_quality_explains_no_xbrl_block(db_session):
    ticker = Ticker(symbol="NEWREG", cik="0000000044")
    db_session.add_all([
        ticker,
        DataImportRun(
            source="sec_facts",
            status="promoted",
            validation_json=json.dumps({
                "setup_blocked_ciks": [ticker.cik],
                "no_xbrl_ciks": [ticker.cik],
                "no_xbrl_filings": [],
            }),
            started_at=datetime.now(timezone.utc),
        ),
    ])
    await db_session.flush()

    quality = await fundamentals_quality_service.ticker_quality(db_session, "NEWREG")
    assert quality.eligible is False
    assert quality.code == "no_xbrl_filings"
    assert "CIK override" in (quality.message or "")
    assert await fundamentals_quality_service.ticker_is_eligible(
        db_session, ticker.id
    ) is False
