"""Deterministic seed data for integration test sandbox.

All UUIDs and timestamps are hardcoded for reproducible assertions.
No external API calls — all data is synthetic.

Usage:
    python -m tests.integration.seed_sandbox

Environment variables:
    POSTGRES_HOST, POSTGRES_PORT, POSTGRES_DB, POSTGRES_USER, POSTGRES_PASSWORD
"""

import asyncio
import json
import os
from datetime import date, datetime, timedelta, timezone
from uuid import UUID

import asyncpg

# ── Fixed base timestamp ─────────────────────────────────────
BASE_TS = datetime(2025, 1, 15, 12, 0, 0, tzinfo=timezone.utc)
BASE_DATE = date(2025, 1, 15)

# ── Deterministic UUIDs ──────────────────────────────────────

# Companies
COMPANY_AAPL = UUID("00000000-0000-4000-a000-000000000001")
COMPANY_MSFT = UUID("00000000-0000-4000-a000-000000000002")
COMPANY_JPM = UUID("00000000-0000-4000-a000-000000000003")
COMPANY_JNJ = UUID("00000000-0000-4000-a000-000000000004")
COMPANY_XOM = UUID("00000000-0000-4000-a000-000000000005")

# Sources (one per company)
SOURCE_AAPL = UUID("00000000-0000-4000-b000-000000000001")
SOURCE_MSFT = UUID("00000000-0000-4000-b000-000000000002")
SOURCE_JPM = UUID("00000000-0000-4000-b000-000000000003")
SOURCE_JNJ = UUID("00000000-0000-4000-b000-000000000004")
SOURCE_XOM = UUID("00000000-0000-4000-b000-000000000005")

# Company aliases
ALIAS_AAPL = UUID("00000000-0000-4000-b100-000000000001")
ALIAS_MSFT = UUID("00000000-0000-4000-b100-000000000002")
ALIAS_JPM = UUID("00000000-0000-4000-b100-000000000003")
ALIAS_JNJ = UUID("00000000-0000-4000-b100-000000000004")
ALIAS_XOM = UUID("00000000-0000-4000-b100-000000000005")

# Competitor relationships
COMPETITOR_REL_1 = UUID("00000000-0000-4000-b200-000000000001")
COMPETITOR_REL_2 = UUID("00000000-0000-4000-b200-000000000002")

# Documents (10)
DOC_01 = UUID("00000000-0000-4000-c000-000000000001")
DOC_02 = UUID("00000000-0000-4000-c000-000000000002")
DOC_03 = UUID("00000000-0000-4000-c000-000000000003")
DOC_04 = UUID("00000000-0000-4000-c000-000000000004")
DOC_05 = UUID("00000000-0000-4000-c000-000000000005")
DOC_06 = UUID("00000000-0000-4000-c000-000000000006")
DOC_07 = UUID("00000000-0000-4000-c000-000000000007")
DOC_08 = UUID("00000000-0000-4000-c000-000000000008")
DOC_09 = UUID("00000000-0000-4000-c000-000000000009")
DOC_10 = UUID("00000000-0000-4000-c000-000000000010")

# Document intelligence (one per document)
INTEL_01 = UUID("00000000-0000-4000-c100-000000000001")
INTEL_02 = UUID("00000000-0000-4000-c100-000000000002")
INTEL_03 = UUID("00000000-0000-4000-c100-000000000003")
INTEL_04 = UUID("00000000-0000-4000-c100-000000000004")
INTEL_05 = UUID("00000000-0000-4000-c100-000000000005")
INTEL_06 = UUID("00000000-0000-4000-c100-000000000006")
INTEL_07 = UUID("00000000-0000-4000-c100-000000000007")
INTEL_08 = UUID("00000000-0000-4000-c100-000000000008")
INTEL_09 = UUID("00000000-0000-4000-c100-000000000009")
INTEL_10 = UUID("00000000-0000-4000-c100-000000000010")

# Document impact records
IMPACT_01 = UUID("00000000-0000-4000-c200-000000000001")
IMPACT_02 = UUID("00000000-0000-4000-c200-000000000002")
IMPACT_03 = UUID("00000000-0000-4000-c200-000000000003")
IMPACT_04 = UUID("00000000-0000-4000-c200-000000000004")
IMPACT_05 = UUID("00000000-0000-4000-c200-000000000005")
IMPACT_06 = UUID("00000000-0000-4000-c200-000000000006")
IMPACT_07 = UUID("00000000-0000-4000-c200-000000000007")
IMPACT_08 = UUID("00000000-0000-4000-c200-000000000008")
IMPACT_09 = UUID("00000000-0000-4000-c200-000000000009")
IMPACT_10 = UUID("00000000-0000-4000-c200-000000000010")

# Document company mentions
MENTION_01 = UUID("00000000-0000-4000-c300-000000000001")
MENTION_02 = UUID("00000000-0000-4000-c300-000000000002")
MENTION_03 = UUID("00000000-0000-4000-c300-000000000003")
MENTION_04 = UUID("00000000-0000-4000-c300-000000000004")
MENTION_05 = UUID("00000000-0000-4000-c300-000000000005")
MENTION_06 = UUID("00000000-0000-4000-c300-000000000006")
MENTION_07 = UUID("00000000-0000-4000-c300-000000000007")
MENTION_08 = UUID("00000000-0000-4000-c300-000000000008")
MENTION_09 = UUID("00000000-0000-4000-c300-000000000009")
MENTION_10 = UUID("00000000-0000-4000-c300-000000000010")

# Trend windows (5)
TREND_01 = UUID("00000000-0000-4000-d000-000000000001")
TREND_02 = UUID("00000000-0000-4000-d000-000000000002")
TREND_03 = UUID("00000000-0000-4000-d000-000000000003")
TREND_04 = UUID("00000000-0000-4000-d000-000000000004")
TREND_05 = UUID("00000000-0000-4000-d000-000000000005")

# Trend projections (one per trend)
PROJECTION_01 = UUID("00000000-0000-4000-d100-000000000001")
PROJECTION_02 = UUID("00000000-0000-4000-d100-000000000002")
PROJECTION_03 = UUID("00000000-0000-4000-d100-000000000003")
PROJECTION_04 = UUID("00000000-0000-4000-d100-000000000004")
PROJECTION_05 = UUID("00000000-0000-4000-d100-000000000005")

# Recommendations (5)
REC_01 = UUID("00000000-0000-4000-e000-000000000001")
REC_02 = UUID("00000000-0000-4000-e000-000000000002")
REC_03 = UUID("00000000-0000-4000-e000-000000000003")
REC_04 = UUID("00000000-0000-4000-e000-000000000004")
REC_05 = UUID("00000000-0000-4000-e000-000000000005")

# Recommendation evidence (one per recommendation)
REC_EV_01 = UUID("00000000-0000-4000-e100-000000000001")
REC_EV_02 = UUID("00000000-0000-4000-e100-000000000002")
REC_EV_03 = UUID("00000000-0000-4000-e100-000000000003")
REC_EV_04 = UUID("00000000-0000-4000-e100-000000000004")
REC_EV_05 = UUID("00000000-0000-4000-e100-000000000005")

# Risk evaluations
RISK_EVAL_01 = UUID("00000000-0000-4000-e200-000000000001")

# Broker account
BROKER_ACCT_01 = UUID("00000000-0000-4000-f000-000000000001")

# Orders (3)
ORDER_01 = UUID("00000000-0000-4000-f100-000000000001")
ORDER_02 = UUID("00000000-0000-4000-f100-000000000002")
ORDER_03 = UUID("00000000-0000-4000-f100-000000000003")

# Order events
ORDER_EVT_01 = UUID("00000000-0000-4000-f200-000000000001")
ORDER_EVT_02 = UUID("00000000-0000-4000-f200-000000000002")
ORDER_EVT_03 = UUID("00000000-0000-4000-f200-000000000003")
ORDER_EVT_04 = UUID("00000000-0000-4000-f200-000000000004")
ORDER_EVT_05 = UUID("00000000-0000-4000-f200-000000000005")

# Positions (2)
POSITION_01 = UUID("00000000-0000-4000-f300-000000000001")
POSITION_02 = UUID("00000000-0000-4000-f300-000000000002")

# Global events (2)
GLOBAL_EVT_01 = UUID("00000000-0000-4000-a100-000000000001")
GLOBAL_EVT_02 = UUID("00000000-0000-4000-a100-000000000002")

# Macro impact records (4 — 2 per global event, across multiple companies)
MACRO_IMPACT_01 = UUID("00000000-0000-4000-a200-000000000001")
MACRO_IMPACT_02 = UUID("00000000-0000-4000-a200-000000000002")
MACRO_IMPACT_03 = UUID("00000000-0000-4000-a200-000000000003")
MACRO_IMPACT_04 = UUID("00000000-0000-4000-a200-000000000004")

# Exposure profiles (2)
EXPOSURE_01 = UUID("00000000-0000-4000-a300-000000000001")
EXPOSURE_02 = UUID("00000000-0000-4000-a300-000000000002")

# Competitive signal records (2)
COMP_SIGNAL_01 = UUID("00000000-0000-4000-a400-000000000001")
COMP_SIGNAL_02 = UUID("00000000-0000-4000-a400-000000000002")

# Trading decisions
TRADING_DECISION_01 = UUID("00000000-0000-4000-a500-000000000001")

# Portfolio snapshot
PORTFOLIO_SNAP_01 = UUID("00000000-0000-4000-a600-000000000001")

# AI agents (use slugs to match migration 026 seed rows)
AGENT_EXTRACTOR = UUID("00000000-0000-4000-a700-000000000001")
AGENT_CLASSIFIER = UUID("00000000-0000-4000-a700-000000000002")
AGENT_THESIS = UUID("00000000-0000-4000-a700-000000000003")

# Agent variants (1 per agent)
VARIANT_EXTRACTOR = UUID("00000000-0000-4000-a800-000000000001")
VARIANT_CLASSIFIER = UUID("00000000-0000-4000-a800-000000000002")
VARIANT_THESIS = UUID("00000000-0000-4000-a800-000000000003")

# Agent performance log entries
PERF_LOG_01 = UUID("00000000-0000-4000-a900-000000000001")
PERF_LOG_02 = UUID("00000000-0000-4000-a900-000000000002")
PERF_LOG_03 = UUID("00000000-0000-4000-a900-000000000003")

# Risk config
RISK_CONFIG_01 = UUID("00000000-0000-4000-aa00-000000000001")

# Audit events
AUDIT_01 = UUID("00000000-0000-4000-ab00-000000000001")
AUDIT_02 = UUID("00000000-0000-4000-ab00-000000000002")
AUDIT_03 = UUID("00000000-0000-4000-ab00-000000000003")

# Watchlists
WATCHLIST_01 = UUID("00000000-0000-4000-ac00-000000000001")
WATCHLIST_02 = UUID("00000000-0000-4000-ac00-000000000002")

# Watchlist members
WL_MEMBER_01 = UUID("00000000-0000-4000-ac10-000000000001")
WL_MEMBER_02 = UUID("00000000-0000-4000-ac10-000000000002")
WL_MEMBER_03 = UUID("00000000-0000-4000-ac10-000000000003")

# Operator Approvals
APPROVAL_PENDING = UUID("00000000-0000-4000-ad00-000000000001")
APPROVAL_APPROVED = UUID("00000000-0000-4000-ad00-000000000002")

# Symbol Lockouts
LOCKOUT_ACTIVE = UUID("00000000-0000-4000-ae00-000000000001")
LOCKOUT_EXPIRED = UUID("00000000-0000-4000-ae00-000000000002")

# Notifications
NOTIFICATION_01 = UUID("00000000-0000-4000-af00-000000000001")

# Ingestion Runs
INGESTION_RUN_01 = UUID("00000000-0000-4000-b300-000000000001")
INGESTION_RUN_02 = UUID("00000000-0000-4000-b300-000000000002")

# Saved Queries
SAVED_QUERY_01 = UUID("00000000-0000-4000-b400-000000000001")

# Daily Risk Snapshot
RISK_SNAPSHOT_01 = UUID("00000000-0000-4000-b500-000000000001")

# ── Exported lookup dicts for test imports ────────────────────

SEED_COMPANY_IDS = {
    "AAPL": str(COMPANY_AAPL),
    "MSFT": str(COMPANY_MSFT),
    "JPM": str(COMPANY_JPM),
    "JNJ": str(COMPANY_JNJ),
    "XOM": str(COMPANY_XOM),
}

SEED_DOCUMENT_IDS = {
    f"DOC_{i:02d}": str(uid)
    for i, uid in enumerate(
        [DOC_01, DOC_02, DOC_03, DOC_04, DOC_05,
         DOC_06, DOC_07, DOC_08, DOC_09, DOC_10],
        start=1,
    )
}

SEED_TREND_IDS = {
    f"TREND_{i:02d}": str(uid)
    for i, uid in enumerate(
        [TREND_01, TREND_02, TREND_03, TREND_04, TREND_05], start=1
    )
}

SEED_RECOMMENDATION_IDS = {
    f"REC_{i:02d}": str(uid)
    for i, uid in enumerate(
        [REC_01, REC_02, REC_03, REC_04, REC_05], start=1
    )
}

SEED_ORDER_IDS = {
    f"ORDER_{i:02d}": str(uid)
    for i, uid in enumerate([ORDER_01, ORDER_02, ORDER_03], start=1)
}

SEED_POSITION_IDS = {
    f"POS_{i:02d}": str(uid)
    for i, uid in enumerate([POSITION_01, POSITION_02], start=1)
}

SEED_GLOBAL_EVENT_IDS = {
    f"EVT_{i:02d}": str(uid)
    for i, uid in enumerate([GLOBAL_EVT_01, GLOBAL_EVT_02], start=1)
}

SEED_AGENT_IDS = {
    "extractor": str(AGENT_EXTRACTOR),
    "classifier": str(AGENT_CLASSIFIER),
    "thesis": str(AGENT_THESIS),
}

SEED_VARIANT_IDS = {
    "extractor": str(VARIANT_EXTRACTOR),
    "classifier": str(VARIANT_CLASSIFIER),
    "thesis": str(VARIANT_THESIS),
}

SEED_BROKER_ACCOUNT_ID = str(BROKER_ACCT_01)
SEED_TRADING_DECISION_ID = str(TRADING_DECISION_01)
SEED_PORTFOLIO_SNAPSHOT_ID = str(PORTFOLIO_SNAP_01)
SEED_RISK_CONFIG_ID = str(RISK_CONFIG_01)

SEED_WATCHLIST_IDS = {
    "WL_01": str(WATCHLIST_01),
    "WL_02": str(WATCHLIST_02),
}
SEED_APPROVAL_IDS = {
    "PENDING": str(APPROVAL_PENDING),
    "APPROVED": str(APPROVAL_APPROVED),
}
SEED_LOCKOUT_IDS = {
    "ACTIVE": str(LOCKOUT_ACTIVE),
    "EXPIRED": str(LOCKOUT_EXPIRED),
}
SEED_NOTIFICATION_IDS = {"NOTIF_01": str(NOTIFICATION_01)}
SEED_INGESTION_RUN_IDS = {
    "RUN_01": str(INGESTION_RUN_01),
    "RUN_02": str(INGESTION_RUN_02),
}
SEED_SAVED_QUERY_IDS = {"SQ_01": str(SAVED_QUERY_01)}
SEED_RISK_SNAPSHOT_IDS = {"SNAP_01": str(RISK_SNAPSHOT_01)}


# ── Seed function ─────────────────────────────────────────────


async def seed() -> None:
    """Populate the database with deterministic test data."""
    dsn = (
        f"postgresql://{os.environ['POSTGRES_USER']}"
        f":{os.environ['POSTGRES_PASSWORD']}"
        f"@{os.environ['POSTGRES_HOST']}"
        f":{os.environ.get('POSTGRES_PORT', '5432')}"
        f"/{os.environ['POSTGRES_DB']}"
    )
    conn = await asyncpg.connect(dsn)
    try:
        await _seed_companies(conn)
        await _seed_sources(conn)
        await _seed_aliases(conn)
        await _seed_competitor_relationships(conn)
        await _seed_documents(conn)
        await _seed_document_mentions(conn)
        await _seed_document_intelligence(conn)
        await _seed_document_impact_records(conn)
        await _seed_trend_windows(conn)
        await _seed_trend_projections(conn)
        await _seed_recommendations(conn)
        await _seed_recommendation_evidence(conn)
        await _seed_risk_evaluations(conn)
        await _seed_broker_accounts(conn)
        await _seed_orders(conn)
        await _seed_order_events(conn)
        await _seed_positions(conn)
        await _seed_global_events(conn)
        await _seed_macro_impact_records(conn)
        await _seed_exposure_profiles(conn)
        await _seed_competitive_signals(conn)
        await _seed_trading_engine_config(conn)
        await _seed_trading_decisions(conn)
        await _seed_portfolio_snapshots(conn)
        await _seed_ai_agents(conn)
        await _seed_agent_variants(conn)
        await _seed_agent_performance_log(conn)
        await _seed_risk_configs(conn)
        await _seed_audit_events(conn)
        await _seed_watchlists(conn)
        await _seed_operator_approvals(conn)
        await _seed_symbol_lockouts(conn)
        await _seed_notifications(conn)
        await _seed_ingestion_runs(conn)
        await _seed_saved_queries(conn)
        await _seed_daily_risk_snapshots(conn)
    finally:
        await conn.close()


# ── Companies ─────────────────────────────────────────────────


async def _seed_companies(conn: asyncpg.Connection) -> None:
    companies = [
        (COMPANY_AAPL, "AAPL", "Apple Inc", "NASDAQ", "Technology", "Consumer Electronics", "mega", True, BASE_TS),
        (COMPANY_MSFT, "MSFT", "Microsoft Corp", "NASDAQ", "Technology", "Software - Infrastructure", "mega", True, BASE_TS),
        (COMPANY_JPM, "JPM", "JPMorgan Chase & Co", "NYSE", "Financial Services", "Banks - Diversified", "mega", True, BASE_TS),
        (COMPANY_JNJ, "JNJ", "Johnson & Johnson", "NYSE", "Healthcare", "Drug Manufacturers", "mega", True, BASE_TS),
        (COMPANY_XOM, "XOM", "Exxon Mobil Corp", "NYSE", "Energy", "Oil & Gas Integrated", "mega", True, BASE_TS),
    ]
    await conn.executemany(
        """INSERT INTO companies (id, ticker, legal_name, exchange, sector, industry, market_cap_bucket, active, created_at)
           VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9)
           ON CONFLICT DO NOTHING""",
        companies,
    )


# ── Sources ───────────────────────────────────────────────────


async def _seed_sources(conn: asyncpg.Connection) -> None:
    sources = [
        (SOURCE_AAPL, COMPANY_AAPL, "news", "Polygon News", json.dumps({"provider": "polygon"}), 0.8, True, BASE_TS),
        (SOURCE_MSFT, COMPANY_MSFT, "news", "Polygon News", json.dumps({"provider": "polygon"}), 0.8, True, BASE_TS),
        (SOURCE_JPM, COMPANY_JPM, "filing", "SEC EDGAR", json.dumps({"cik": "0000019617"}), 0.95, True, BASE_TS),
        (SOURCE_JNJ, COMPANY_JNJ, "news", "Polygon News", json.dumps({"provider": "polygon"}), 0.8, True, BASE_TS),
        (SOURCE_XOM, COMPANY_XOM, "news", "Polygon News", json.dumps({"provider": "polygon"}), 0.8, True, BASE_TS),
    ]
    await conn.executemany(
        """INSERT INTO sources (id, company_id, source_type, source_name, config, credibility_score, active, created_at)
           VALUES ($1, $2, $3, $4, $5::jsonb, $6, $7, $8)
           ON CONFLICT DO NOTHING""",
        sources,
    )


# ── Aliases ───────────────────────────────────────────────────


async def _seed_aliases(conn: asyncpg.Connection) -> None:
    aliases = [
        (ALIAS_AAPL, COMPANY_AAPL, "Apple", "brand", BASE_TS),
        (ALIAS_MSFT, COMPANY_MSFT, "Microsoft", "brand", BASE_TS),
        (ALIAS_JPM, COMPANY_JPM, "JP Morgan", "brand", BASE_TS),
        (ALIAS_JNJ, COMPANY_JNJ, "J&J", "brand", BASE_TS),
        (ALIAS_XOM, COMPANY_XOM, "Exxon", "brand", BASE_TS),
    ]
    await conn.executemany(
        """INSERT INTO company_aliases (id, company_id, alias, alias_type, created_at)
           VALUES ($1, $2, $3, $4, $5)
           ON CONFLICT DO NOTHING""",
        aliases,
    )


# ── Competitor Relationships ──────────────────────────────────


async def _seed_competitor_relationships(conn: asyncpg.Connection) -> None:
    rels = [
        (COMPETITOR_REL_1, COMPANY_AAPL, COMPANY_MSFT, "direct_rival", 0.85, True, "manual", True, BASE_TS),
        (COMPETITOR_REL_2, COMPANY_JPM, COMPANY_JNJ, "same_sector", 0.3, True, "inferred", True, BASE_TS),
    ]
    await conn.executemany(
        """INSERT INTO competitor_relationships
           (id, company_a_id, company_b_id, relationship_type, strength, bidirectional, source, active, created_at)
           VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9)
           ON CONFLICT DO NOTHING""",
        rels,
    )


# ── Documents (10) ────────────────────────────────────────────


async def _seed_documents(conn: asyncpg.Connection) -> None:
    # Mix: 6 news, 2 filings, 2 macro_event
    docs = [
        (DOC_01, "news", "news", "Reuters", "https://example.com/aapl-1", "Apple Q4 Earnings Beat", BASE_TS - timedelta(days=5), "hash_doc_01", "ingested", BASE_TS),
        (DOC_02, "news", "news", "Bloomberg", "https://example.com/msft-1", "Microsoft Cloud Revenue Surges", BASE_TS - timedelta(days=4), "hash_doc_02", "processed", BASE_TS),
        (DOC_03, "filing", "filing", "SEC EDGAR", "https://sec.gov/jpm-10k", "JPM Annual Report 10-K", BASE_TS - timedelta(days=10), "hash_doc_03", "processed", BASE_TS),
        (DOC_04, "news", "news", "CNBC", "https://example.com/jnj-1", "J&J Drug Trial Results", BASE_TS - timedelta(days=3), "hash_doc_04", "processed", BASE_TS),
        (DOC_05, "news", "news", "Reuters", "https://example.com/xom-1", "Exxon Oil Production Update", BASE_TS - timedelta(days=2), "hash_doc_05", "processed", BASE_TS),
        (DOC_06, "news", "news", "WSJ", "https://example.com/aapl-2", "Apple Vision Pro Sales", BASE_TS - timedelta(days=1), "hash_doc_06", "processed", BASE_TS),
        (DOC_07, "filing", "filing", "SEC EDGAR", "https://sec.gov/msft-10q", "MSFT Quarterly Filing 10-Q", BASE_TS - timedelta(days=8), "hash_doc_07", "processed", BASE_TS),
        (DOC_08, "macro_event", "news", "Reuters", "https://example.com/fed-1", "Fed Rate Decision January 2025", BASE_TS - timedelta(days=6), "hash_doc_08", "processed", BASE_TS),
        (DOC_09, "macro_event", "news", "Bloomberg", "https://example.com/trade-1", "US-China Trade Tensions Escalate", BASE_TS - timedelta(days=7), "hash_doc_09", "processed", BASE_TS),
        (DOC_10, "news", "news", "MarketWatch", "https://example.com/jpm-2", "JPM Investment Banking Revenue", BASE_TS - timedelta(days=1), "hash_doc_10", "processed", BASE_TS),
    ]
    await conn.executemany(
        """INSERT INTO documents
           (id, document_type, source_type, publisher, url, title, published_at, content_hash, status, created_at)
           VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10)
           ON CONFLICT DO NOTHING""",
        docs,
    )


# ── Document Company Mentions ─────────────────────────────────


async def _seed_document_mentions(conn: asyncpg.Connection) -> None:
    mentions = [
        (MENTION_01, DOC_01, COMPANY_AAPL, "AAPL", "direct", 0.95, BASE_TS),
        (MENTION_02, DOC_02, COMPANY_MSFT, "MSFT", "direct", 0.95, BASE_TS),
        (MENTION_03, DOC_03, COMPANY_JPM, "JPM", "direct", 0.90, BASE_TS),
        (MENTION_04, DOC_04, COMPANY_JNJ, "JNJ", "direct", 0.90, BASE_TS),
        (MENTION_05, DOC_05, COMPANY_XOM, "XOM", "direct", 0.90, BASE_TS),
        (MENTION_06, DOC_06, COMPANY_AAPL, "AAPL", "direct", 0.95, BASE_TS),
        (MENTION_07, DOC_07, COMPANY_MSFT, "MSFT", "direct", 0.90, BASE_TS),
        (MENTION_08, DOC_08, COMPANY_JPM, "JPM", "indirect", 0.60, BASE_TS),
        (MENTION_09, DOC_09, COMPANY_AAPL, "AAPL", "indirect", 0.50, BASE_TS),
        (MENTION_10, DOC_10, COMPANY_JPM, "JPM", "direct", 0.90, BASE_TS),
    ]
    await conn.executemany(
        """INSERT INTO document_company_mentions
           (id, document_id, company_id, ticker, mention_type, confidence, created_at)
           VALUES ($1, $2, $3, $4, $5, $6, $7)
           ON CONFLICT DO NOTHING""",
        mentions,
    )


# ── Document Intelligence ─────────────────────────────────────


async def _seed_document_intelligence(conn: asyncpg.Connection) -> None:
    intels = [
        (INTEL_01, DOC_01, "Apple beats Q4 expectations with strong iPhone sales.", 0.85, "ollama", "qwen3.5:9b", "document-intel-v2", "2.0.0", "valid", BASE_TS),
        (INTEL_02, DOC_02, "Microsoft Azure revenue grows 29% year-over-year.", 0.90, "ollama", "qwen3.5:9b", "document-intel-v2", "2.0.0", "valid", BASE_TS),
        (INTEL_03, DOC_03, "JPMorgan reports record annual profit driven by investment banking.", 0.88, "ollama", "qwen3.5:9b", "document-intel-v2", "2.0.0", "valid", BASE_TS),
        (INTEL_04, DOC_04, "J&J Phase 3 trial shows positive results for new cancer drug.", 0.82, "ollama", "qwen3.5:9b", "document-intel-v2", "2.0.0", "valid", BASE_TS),
        (INTEL_05, DOC_05, "Exxon increases Permian Basin output by 15%.", 0.78, "ollama", "qwen3.5:9b", "document-intel-v2", "2.0.0", "valid", BASE_TS),
        (INTEL_06, DOC_06, "Apple Vision Pro sees moderate adoption in enterprise segment.", 0.75, "ollama", "qwen3.5:9b", "document-intel-v2", "2.0.0", "valid", BASE_TS),
        (INTEL_07, DOC_07, "Microsoft quarterly filing shows strong cloud and AI growth.", 0.87, "ollama", "qwen3.5:9b", "document-intel-v2", "2.0.0", "valid", BASE_TS),
        (INTEL_08, DOC_08, "Fed holds rates steady, signals potential cuts in Q2.", 0.92, "ollama", "qwen3.5:9b", "event-classification-v1", "1.0.0", "valid", BASE_TS),
        (INTEL_09, DOC_09, "US-China trade tensions rise with new tariff proposals.", 0.88, "ollama", "qwen3.5:9b", "event-classification-v1", "1.0.0", "valid", BASE_TS),
        (INTEL_10, DOC_10, "JPM investment banking fees up 20% in Q4.", 0.80, "ollama", "qwen3.5:9b", "document-intel-v2", "2.0.0", "valid", BASE_TS),
    ]
    await conn.executemany(
        """INSERT INTO document_intelligence
           (id, document_id, summary, confidence, model_provider, model_name, prompt_version, schema_version, validation_status, created_at)
           VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10)
           ON CONFLICT DO NOTHING""",
        intels,
    )


# ── Document Impact Records ───────────────────────────────────


async def _seed_document_impact_records(conn: asyncpg.Connection) -> None:
    impacts = [
        (IMPACT_01, INTEL_01, COMPANY_AAPL, "AAPL", 0.9, "positive", 0.8, "short_term", "earnings", json.dumps(["Strong iPhone sales"]), json.dumps([]), json.dumps(["beat expectations"]), BASE_TS),
        (IMPACT_02, INTEL_02, COMPANY_MSFT, "MSFT", 0.9, "positive", 0.85, "medium_term", "growth", json.dumps(["Azure 29% growth"]), json.dumps([]), json.dumps(["cloud revenue surge"]), BASE_TS),
        (IMPACT_03, INTEL_03, COMPANY_JPM, "JPM", 0.85, "positive", 0.7, "short_term", "earnings", json.dumps(["Record profit"]), json.dumps(["Rate sensitivity"]), json.dumps(["investment banking"]), BASE_TS),
        (IMPACT_04, INTEL_04, COMPANY_JNJ, "JNJ", 0.8, "positive", 0.75, "long_term", "product", json.dumps(["Phase 3 success"]), json.dumps(["Regulatory risk"]), json.dumps(["cancer drug trial"]), BASE_TS),
        (IMPACT_05, INTEL_05, COMPANY_XOM, "XOM", 0.8, "positive", 0.6, "medium_term", "operational", json.dumps(["Production increase"]), json.dumps(["Oil price risk"]), json.dumps(["Permian Basin"]), BASE_TS),
        (IMPACT_06, INTEL_06, COMPANY_AAPL, "AAPL", 0.7, "neutral", 0.4, "medium_term", "product", json.dumps(["Enterprise adoption"]), json.dumps(["Consumer demand weak"]), json.dumps(["Vision Pro"]), BASE_TS),
        (IMPACT_07, INTEL_07, COMPANY_MSFT, "MSFT", 0.85, "positive", 0.8, "medium_term", "growth", json.dumps(["AI and cloud growth"]), json.dumps([]), json.dumps(["quarterly filing"]), BASE_TS),
        (IMPACT_08, INTEL_08, COMPANY_JPM, "JPM", 0.6, "positive", 0.5, "medium_term", "macro", json.dumps(["Rate cut signal"]), json.dumps(["Inflation risk"]), json.dumps(["Fed decision"]), BASE_TS),
        (IMPACT_09, INTEL_09, COMPANY_AAPL, "AAPL", 0.5, "negative", -0.3, "short_term", "geopolitical", json.dumps(["Supply chain risk"]), json.dumps(["Tariff impact"]), json.dumps(["trade tensions"]), BASE_TS),
        (IMPACT_10, INTEL_10, COMPANY_JPM, "JPM", 0.85, "positive", 0.65, "short_term", "earnings", json.dumps(["IB fees up 20%"]), json.dumps([]), json.dumps(["investment banking"]), BASE_TS),
    ]
    await conn.executemany(
        """INSERT INTO document_impact_records
           (id, intelligence_id, company_id, ticker, relevance, sentiment, impact_score,
            impact_horizon, catalyst_type, key_facts, risks, evidence_spans, created_at)
           VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10::jsonb, $11::jsonb, $12::jsonb, $13)
           ON CONFLICT DO NOTHING""",
        impacts,
    )


# ── Trend Windows (5) ────────────────────────────────────────


async def _seed_trend_windows(conn: asyncpg.Connection) -> None:
    # entity_id is VARCHAR, not UUID
    trends = [
        (TREND_01, "company", str(COMPANY_AAPL), "7d", "bullish", 0.72, 0.80,
         json.dumps([{"fact": "Strong iPhone sales", "weight": 0.9}]),
         json.dumps([{"fact": "Trade tensions", "weight": 0.3}]),
         json.dumps(["earnings", "product"]), json.dumps(["tariff_risk"]),
         0.15, json.dumps({"market_phase": "expansion"}), BASE_TS, BASE_TS),
        (TREND_02, "company", str(COMPANY_MSFT), "7d", "bullish", 0.85, 0.88,
         json.dumps([{"fact": "Azure growth 29%", "weight": 0.95}]),
         json.dumps([]),
         json.dumps(["growth", "cloud"]), json.dumps([]),
         0.05, json.dumps({"market_phase": "expansion"}), BASE_TS, BASE_TS),
        (TREND_03, "company", str(COMPANY_JPM), "7d", "bullish", 0.60, 0.70,
         json.dumps([{"fact": "Record profit", "weight": 0.8}]),
         json.dumps([{"fact": "Rate sensitivity", "weight": 0.4}]),
         json.dumps(["earnings"]), json.dumps(["interest_rate_risk"]),
         0.25, json.dumps({"market_phase": "stable"}), BASE_TS, BASE_TS),
        (TREND_04, "company", str(COMPANY_JNJ), "30d", "bullish", 0.55, 0.65,
         json.dumps([{"fact": "Drug trial success", "weight": 0.75}]),
         json.dumps([{"fact": "Regulatory risk", "weight": 0.3}]),
         json.dumps(["product"]), json.dumps(["regulatory"]),
         0.20, json.dumps({"market_phase": "stable"}), BASE_TS, BASE_TS),
        (TREND_05, "company", str(COMPANY_XOM), "7d", "mixed", 0.40, 0.55,
         json.dumps([{"fact": "Production increase", "weight": 0.6}]),
         json.dumps([{"fact": "Oil price volatility", "weight": 0.5}]),
         json.dumps(["operational"]), json.dumps(["commodity_risk"]),
         0.35, json.dumps({"market_phase": "uncertain"}), BASE_TS, BASE_TS),
    ]
    await conn.executemany(
        """INSERT INTO trend_windows
           (id, entity_type, entity_id, "window", trend_direction, trend_strength, confidence,
            top_supporting_evidence, top_opposing_evidence, dominant_catalysts, material_risks,
            contradiction_score, market_context, generated_at, created_at)
           VALUES ($1, $2, $3, $4, $5, $6, $7, $8::jsonb, $9::jsonb, $10::jsonb, $11::jsonb,
                   $12, $13::jsonb, $14, $15)
           ON CONFLICT DO NOTHING""",
        trends,
    )


# ── Trend Projections ─────────────────────────────────────────


async def _seed_trend_projections(conn: asyncpg.Connection) -> None:
    projections = [
        (PROJECTION_01, TREND_01, "bullish", 0.70, 0.75, "7d", json.dumps(["earnings_momentum"]), 0.10, False, BASE_TS),
        (PROJECTION_02, TREND_02, "bullish", 0.88, 0.85, "7d", json.dumps(["cloud_growth"]), 0.05, False, BASE_TS),
        (PROJECTION_03, TREND_03, "bullish", 0.55, 0.60, "7d", json.dumps(["banking_recovery"]), 0.20, False, BASE_TS),
        (PROJECTION_04, TREND_04, "bullish", 0.50, 0.58, "30d", json.dumps(["drug_pipeline"]), 0.15, False, BASE_TS),
        (PROJECTION_05, TREND_05, "bearish", 0.45, 0.50, "7d", json.dumps(["oil_price_decline"]), 0.30, True, BASE_TS),
    ]
    await conn.executemany(
        """INSERT INTO trend_projections
           (id, trend_window_id, projected_direction, projected_strength, projected_confidence,
            projection_horizon, driving_factors, macro_contribution_pct, diverges_from_current, computed_at)
           VALUES ($1, $2, $3, $4, $5, $6, $7::jsonb, $8, $9, $10)
           ON CONFLICT DO NOTHING""",
        projections,
    )


# ── Recommendations (5) ──────────────────────────────────────


async def _seed_recommendations(conn: asyncpg.Connection) -> None:
    recs = [
        (REC_01, "AAPL", COMPANY_AAPL, "buy", "autonomous", 0.80, "7d", "Strong earnings momentum with iPhone sales beat.", json.dumps(["Trade war escalation"]), 0.03, 0.01, "v1.0", BASE_TS, BASE_TS),
        (REC_02, "MSFT", COMPANY_MSFT, "buy", "autonomous", 0.88, "14d", "Azure cloud growth accelerating with AI tailwinds.", json.dumps(["Cloud competition"]), 0.04, 0.008, "v1.0", BASE_TS, BASE_TS),
        (REC_03, "JPM", COMPANY_JPM, "watch", "informational", 0.65, "7d", "Mixed signals: strong IB but rate uncertainty.", json.dumps(["Rate hike"]), 0.02, 0.005, "v1.0", BASE_TS, BASE_TS),
        (REC_04, "JNJ", COMPANY_JNJ, "buy", "paper", 0.70, "30d", "Positive drug trial results support long-term thesis.", json.dumps(["FDA rejection"]), 0.025, 0.007, "v1.0", BASE_TS, BASE_TS),
        (REC_05, "XOM", COMPANY_XOM, "sell", "informational", 0.55, "7d", "Oil price headwinds outweigh production gains.", json.dumps(["Oil price spike"]), 0.02, 0.01, "v1.0", BASE_TS, BASE_TS),
    ]
    await conn.executemany(
        """INSERT INTO recommendations
           (id, ticker, company_id, action, mode, confidence, time_horizon, thesis,
            invalidation_conditions, portfolio_pct, max_loss_pct, model_version, generated_at, created_at)
           VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9::jsonb, $10, $11, $12, $13, $14)
           ON CONFLICT DO NOTHING""",
        recs,
    )


# ── Recommendation Evidence ───────────────────────────────────


async def _seed_recommendation_evidence(conn: asyncpg.Connection) -> None:
    evidence = [
        (REC_EV_01, REC_01, DOC_01, INTEL_01, "supporting", 0.9, BASE_TS),
        (REC_EV_02, REC_02, DOC_02, INTEL_02, "supporting", 0.95, BASE_TS),
        (REC_EV_03, REC_03, DOC_03, INTEL_03, "supporting", 0.7, BASE_TS),
        (REC_EV_04, REC_04, DOC_04, INTEL_04, "supporting", 0.8, BASE_TS),
        (REC_EV_05, REC_05, DOC_05, INTEL_05, "opposing", 0.6, BASE_TS),
    ]
    await conn.executemany(
        """INSERT INTO recommendation_evidence
           (id, recommendation_id, document_id, intelligence_id, evidence_type, weight, created_at)
           VALUES ($1, $2, $3, $4, $5, $6, $7)
           ON CONFLICT DO NOTHING""",
        evidence,
    )


# ── Risk Evaluations ──────────────────────────────────────────


async def _seed_risk_evaluations(conn: asyncpg.Connection) -> None:
    await conn.execute(
        """INSERT INTO risk_evaluations
           (id, recommendation_id, eligible, allowed_mode, rejection_reasons, risk_checks, evaluated_at)
           VALUES ($1, $2, $3, $4, $5::jsonb, $6::jsonb, $7)
           ON CONFLICT DO NOTHING""",
        RISK_EVAL_01, REC_01, True, "autonomous", json.dumps([]),
        json.dumps({"portfolio_heat": "pass", "sector_exposure": "pass", "daily_loss": "pass"}),
        BASE_TS,
    )


# ── Broker Accounts ───────────────────────────────────────────


async def _seed_broker_accounts(conn: asyncpg.Connection) -> None:
    await conn.execute(
        """INSERT INTO broker_accounts (id, provider, account_id, mode, config, active, created_at)
           VALUES ($1, $2, $3, $4, $5::jsonb, $6, $7)
           ON CONFLICT DO NOTHING""",
        BROKER_ACCT_01, "alpaca", "PAPER-001", "paper",
        json.dumps({"base_url": "https://paper-api.alpaca.markets"}),
        True, BASE_TS,
    )


# ── Orders (3: filled, pending, cancelled) ───────────────────


async def _seed_orders(conn: asyncpg.Connection) -> None:
    orders = [
        # Filled order
        (ORDER_01, REC_01, BROKER_ACCT_01, "AAPL", "buy", "market", 10, None, None,
         "filled", "inttest-order-001", "broker-ord-001",
         json.dumps({"reason": "earnings_momentum"}),
         BASE_TS, BASE_TS + timedelta(seconds=5), BASE_TS + timedelta(seconds=30),
         None, None, None, 185.50, 10, BASE_TS, BASE_TS),
        # Pending order
        (ORDER_02, REC_02, BROKER_ACCT_01, "MSFT", "buy", "limit", 5, 410.00, None,
         "pending", "inttest-order-002", None,
         json.dumps({"reason": "cloud_growth"}),
         BASE_TS, None, None,
         None, None, None, None, None, BASE_TS, BASE_TS),
        # Cancelled order
        (ORDER_03, REC_05, BROKER_ACCT_01, "XOM", "sell", "market", 20, None, None,
         "cancelled", "inttest-order-003", "broker-ord-003",
         json.dumps({"reason": "oil_headwinds"}),
         BASE_TS, BASE_TS + timedelta(seconds=3), None,
         BASE_TS + timedelta(minutes=5), None, None, None, None, BASE_TS, BASE_TS),
    ]
    await conn.executemany(
        """INSERT INTO orders
           (id, recommendation_id, broker_account_id, ticker, side, order_type, quantity,
            limit_price, stop_price, status, idempotency_key, broker_order_id, decision_trace,
            submitted_at, acknowledged_at, filled_at, cancelled_at, rejected_at, rejection_reason,
            fill_price, fill_quantity, created_at, updated_at)
           VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13::jsonb,
                   $14, $15, $16, $17, $18, $19, $20, $21, $22, $23)
           ON CONFLICT DO NOTHING""",
        orders,
    )


# ── Order Events ──────────────────────────────────────────────


async def _seed_order_events(conn: asyncpg.Connection) -> None:
    events = [
        (ORDER_EVT_01, ORDER_01, "submitted", json.dumps({"qty": 10}), BASE_TS, BASE_TS),
        (ORDER_EVT_02, ORDER_01, "acknowledged", json.dumps({"broker_id": "broker-ord-001"}), BASE_TS + timedelta(seconds=5), BASE_TS + timedelta(seconds=5)),
        (ORDER_EVT_03, ORDER_01, "filled", json.dumps({"fill_price": 185.50, "fill_qty": 10}), BASE_TS + timedelta(seconds=30), BASE_TS + timedelta(seconds=30)),
        (ORDER_EVT_04, ORDER_02, "submitted", json.dumps({"qty": 5, "limit": 410.00}), BASE_TS, BASE_TS),
        (ORDER_EVT_05, ORDER_03, "cancelled", json.dumps({"reason": "user_request"}), BASE_TS + timedelta(minutes=5), BASE_TS + timedelta(minutes=5)),
    ]
    await conn.executemany(
        """INSERT INTO order_events (id, order_id, event_type, data, broker_timestamp, created_at)
           VALUES ($1, $2, $3, $4::jsonb, $5, $6)
           ON CONFLICT DO NOTHING""",
        events,
    )


# ── Positions (2) ─────────────────────────────────────────────


async def _seed_positions(conn: asyncpg.Connection) -> None:
    positions = [
        (POSITION_01, BROKER_ACCT_01, "AAPL", 10, 185.50, 192.30, 68.00, 0.0, BASE_TS),
        (POSITION_02, BROKER_ACCT_01, "MSFT", 15, 405.00, 412.75, 116.25, 50.00, BASE_TS),
    ]
    await conn.executemany(
        """INSERT INTO positions
           (id, broker_account_id, ticker, quantity, avg_entry_price, current_price,
            unrealized_pnl, realized_pnl, updated_at)
           VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9)
           ON CONFLICT DO NOTHING""",
        positions,
    )


# ── Global Events (2) ────────────────────────────────────────


async def _seed_global_events(conn: asyncpg.Connection) -> None:
    events = [
        (GLOBAL_EVT_01, ["interest_rate_decision"], "medium",
         ["North America"], ["Financial Services", "Real Estate"],
         [], "Federal Reserve holds rates steady, signals potential cuts in Q2 2025.",
         json.dumps(["Fed holds rates", "Potential Q2 cuts", "Inflation moderating"]),
         "weeks", 0.88, DOC_08, "ollama", "qwen3.5:9b", "event-classification-v1", "1.0.0", BASE_TS),
        (GLOBAL_EVT_02, ["trade_war", "tariff"], "high",
         ["North America", "East Asia"], ["Technology", "Consumer Electronics"],
         [], "US-China trade tensions escalate with new tariff proposals on tech imports.",
         json.dumps(["New tariffs proposed", "Tech sector targeted", "Supply chain disruption"]),
         "months", 0.82, DOC_09, "ollama", "qwen3.5:9b", "event-classification-v1", "1.0.0", BASE_TS),
    ]
    await conn.executemany(
        """INSERT INTO global_events
           (id, event_types, severity, affected_regions, affected_sectors, affected_commodities,
            summary, key_facts, estimated_duration, confidence, source_document_id,
            model_provider, model_name, prompt_version, schema_version, created_at)
           VALUES ($1, $2, $3, $4, $5, $6, $7, $8::jsonb, $9, $10, $11, $12, $13, $14, $15, $16)
           ON CONFLICT DO NOTHING""",
        events,
    )


# ── Macro Impact Records (4) ─────────────────────────────────


async def _seed_macro_impact_records(conn: asyncpg.Connection) -> None:
    records = [
        # Fed rate decision impacts JPM and JNJ
        (MACRO_IMPACT_01, GLOBAL_EVT_01, COMPANY_JPM, "JPM", 0.75, "positive",
         json.dumps(["Rate-sensitive banking sector benefits"]), 0.80, BASE_TS),
        (MACRO_IMPACT_02, GLOBAL_EVT_01, COMPANY_JNJ, "JNJ", 0.25, "neutral",
         json.dumps(["Healthcare less rate-sensitive"]), 0.70, BASE_TS),
        # Trade tensions impact AAPL and MSFT
        (MACRO_IMPACT_03, GLOBAL_EVT_02, COMPANY_AAPL, "AAPL", -0.60, "negative",
         json.dumps(["China manufacturing exposure", "Tariff on electronics"]), 0.85, BASE_TS),
        (MACRO_IMPACT_04, GLOBAL_EVT_02, COMPANY_MSFT, "MSFT", -0.30, "negative",
         json.dumps(["Cloud infrastructure less exposed"]), 0.75, BASE_TS),
    ]
    await conn.executemany(
        """INSERT INTO macro_impact_records
           (id, event_id, company_id, ticker, macro_impact_score, impact_direction,
            contributing_factors, confidence, computed_at)
           VALUES ($1, $2, $3, $4, $5, $6, $7::jsonb, $8, $9)
           ON CONFLICT DO NOTHING""",
        records,
    )


# ── Exposure Profiles (2) ────────────────────────────────────


async def _seed_exposure_profiles(conn: asyncpg.Connection) -> None:
    profiles = [
        (EXPOSURE_01, COMPANY_AAPL,
         json.dumps({"North America": 0.45, "Europe": 0.25, "China": 0.20, "Rest of Asia": 0.10}),
         ["China", "Taiwan", "India"], ["semiconductors", "rare_earth"],
         ["US", "EU", "China"], "global_leader", 0.55, "manual", 1.0, 1, True, BASE_TS, BASE_TS),
        (EXPOSURE_02, COMPANY_JPM,
         json.dumps({"North America": 0.70, "Europe": 0.20, "Asia": 0.10}),
         ["North America", "Europe"], [],
         ["US", "UK", "EU"], "global_leader", 0.30, "manual", 1.0, 1, True, BASE_TS, BASE_TS),
    ]
    await conn.executemany(
        """INSERT INTO exposure_profiles
           (id, company_id, geographic_revenue_mix, supply_chain_regions, key_input_commodities,
            regulatory_jurisdictions, market_position_tier, export_dependency_pct,
            source, confidence, version, active, created_at, updated_at)
           VALUES ($1, $2, $3::jsonb, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14)
           ON CONFLICT DO NOTHING""",
        profiles,
    )


# ── Competitive Signal Records (2) ───────────────────────────


async def _seed_competitive_signals(conn: asyncpg.Connection) -> None:
    signals = [
        (COMP_SIGNAL_01, DOC_01, "AAPL", "MSFT", "earnings_beat", 0.75,
         "positive", 0.6, 0.85, BASE_TS),
        (COMP_SIGNAL_02, DOC_05, "XOM", "JPM", "production_change", 0.50,
         "neutral", 0.3, 0.30, BASE_TS),
    ]
    await conn.executemany(
        """INSERT INTO competitive_signal_records
           (id, source_document_id, source_ticker, target_ticker, catalyst_type,
            pattern_confidence, signal_direction, signal_strength, relationship_strength, computed_at)
           VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10)
           ON CONFLICT DO NOTHING""",
        signals,
    )


# ── Trading Engine Config (UPDATE existing row from migration 018) ─


async def _seed_trading_engine_config(conn: asyncpg.Connection) -> None:
    # Migration 018 inserts a default row. Update it rather than insert.
    await conn.execute(
        """UPDATE trading_engine_config
           SET enabled = TRUE,
               paused = FALSE,
               risk_tier = 'moderate',
               max_open_positions = 10,
               updated_at = $1""",
        BASE_TS,
    )


# ── Trading Decisions ─────────────────────────────────────────


async def _seed_trading_decisions(conn: asyncpg.Connection) -> None:
    await conn.execute(
        """INSERT INTO trading_decisions
           (id, recommendation_id, decision, ticker, computed_position_size,
            computed_share_quantity, risk_tier_at_decision, portfolio_heat_at_decision,
            active_pool_at_decision, reserve_pool_at_decision, circuit_breaker_status,
            correlation_check_result, sector_exposure_check_result,
            earnings_proximity_flag, is_micro_trade, decision_trace, created_at)
           VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11,
                   $12::jsonb, $13::jsonb, $14, $15, $16::jsonb, $17)
           ON CONFLICT DO NOTHING""",
        TRADING_DECISION_01, REC_01, "execute", "AAPL", 1855.00, 10,
        "moderate", 0.15, 10000.00, 2500.00, "inactive",
        json.dumps({"correlated_tickers": [], "max_correlation": 0.0}),
        json.dumps({"Technology": 0.15}),
        False, False,
        json.dumps({"recommendation_id": str(REC_01), "action": "buy", "confidence": 0.80}),
        BASE_TS,
    )


# ── Portfolio Snapshots ───────────────────────────────────────


async def _seed_portfolio_snapshots(conn: asyncpg.Connection) -> None:
    await conn.execute(
        """INSERT INTO portfolio_snapshots
           (id, snapshot_date, portfolio_value, active_pool, reserve_pool,
            daily_return, cumulative_return, unrealized_pnl, realized_pnl,
            win_count, loss_count, win_rate, sharpe_ratio, max_drawdown,
            current_drawdown_pct, portfolio_heat, risk_tier, positions, metrics, created_at)
           VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17,
                   $18::jsonb, $19::jsonb, $20)
           ON CONFLICT DO NOTHING""",
        PORTFOLIO_SNAP_01, BASE_DATE, 12500.00, 10000.00, 2500.00,
        0.012, 0.025, 184.25, 50.00,
        3, 1, 0.75, 1.45, 0.03, 0.01, 0.15, "moderate",
        json.dumps([
            {"ticker": "AAPL", "quantity": 10, "unrealized_pnl": 68.00},
            {"ticker": "MSFT", "quantity": 15, "unrealized_pnl": 116.25},
        ]),
        json.dumps({"total_trades": 4, "avg_hold_days": 5}),
        BASE_TS,
    )


# ── AI Agents (3 — match migration 026 slugs, use ON CONFLICT) ─


async def _seed_ai_agents(conn: asyncpg.Connection) -> None:
    # Migration 026 seeds these by slug. We insert with our deterministic IDs
    # using ON CONFLICT on slug to capture the ID if already present.
    # First, try to insert; if slug exists, just update the id isn't possible
    # so we delete-and-reinsert with our IDs for test determinism.
    # Safer approach: delete existing system agents and re-insert with our IDs.
    await conn.execute(
        "DELETE FROM agent_performance_log WHERE agent_id IN (SELECT id FROM ai_agents WHERE slug IN ('document-extractor', 'event-classifier', 'thesis-rewriter'))"
    )
    await conn.execute(
        "DELETE FROM agent_variants WHERE agent_id IN (SELECT id FROM ai_agents WHERE slug IN ('document-extractor', 'event-classifier', 'thesis-rewriter'))"
    )
    await conn.execute(
        "DELETE FROM ai_agents WHERE slug IN ('document-extractor', 'event-classifier', 'thesis-rewriter')"
    )

    agents = [
        (AGENT_EXTRACTOR, "Document Intelligence Extractor", "document-extractor",
         "Extracts structured intelligence from documents.",
         "ollama", "qwen3.5:9b-fast", "You are a financial document analyst.", "document-intel-v2", "2.0.0",
         0.0, 32768, 120, 2, True, "system", BASE_TS, BASE_TS),
        (AGENT_CLASSIFIER, "Global Event Classifier", "event-classifier",
         "Classifies global news into structured macro events.",
         "ollama", "qwen3.5:9b-fast", "You classify MACRO-LEVEL global news.", "event-classification-v1", "1.0.0",
         0.0, 32768, 120, 2, True, "system", BASE_TS, BASE_TS),
        (AGENT_THESIS, "Thesis Rewriter", "thesis-rewriter",
         "Rewrites trade thesis summaries into professional prose.",
         "ollama", "qwen3.5:9b-fast", "You are a concise financial analyst.", "thesis-rewrite-v1", "1.0.0",
         0.0, 32768, 120, 2, True, "system", BASE_TS, BASE_TS),
    ]
    await conn.executemany(
        """INSERT INTO ai_agents
           (id, name, slug, purpose, model_provider, model_name, system_prompt,
            prompt_version, schema_version, temperature, max_tokens, timeout_seconds,
            max_retries, active, source, created_at, updated_at)
           VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17)""",
        agents,
    )


# ── Agent Variants (1 per agent) ─────────────────────────────


async def _seed_agent_variants(conn: asyncpg.Connection) -> None:
    variants = [
        (VARIANT_EXTRACTOR, AGENT_EXTRACTOR, "Extractor GPT-4o Variant", "extractor-gpt4o",
         "Testing GPT-4o for extraction quality comparison.",
         "openai", "gpt-4o", "You are a financial document analyst.", "",
         "document-intel-v2-gpt4o", 0.1, 16384, 0, 0, 0, 60, 3, False, BASE_TS, BASE_TS),
        (VARIANT_CLASSIFIER, AGENT_CLASSIFIER, "Classifier Claude Variant", "classifier-claude",
         "Testing Claude for event classification.",
         "anthropic", "claude-sonnet-4-20250514", "You classify MACRO-LEVEL global news.", "",
         "event-classification-v1-claude", 0.0, 16384, 0, 0, 0, 90, 2, False, BASE_TS, BASE_TS),
        (VARIANT_THESIS, AGENT_THESIS, "Thesis GPT-4o-mini Variant", "thesis-gpt4o-mini",
         "Testing GPT-4o-mini for thesis rewriting cost efficiency.",
         "openai", "gpt-4o-mini", "You are a concise financial analyst.", "",
         "thesis-rewrite-v1-mini", 0.2, 8192, 0, 0, 0, 30, 2, False, BASE_TS, BASE_TS),
    ]
    await conn.executemany(
        """INSERT INTO agent_variants
           (id, agent_id, variant_name, variant_slug, description,
            model_provider, model_name, system_prompt, user_prompt_template,
            prompt_version, temperature, max_tokens, context_window,
            input_token_limit, token_budget, timeout_seconds, max_retries,
            is_active, created_at, updated_at)
           VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18, $19, $20)
           ON CONFLICT DO NOTHING""",
        variants,
    )


# ── Agent Performance Log ─────────────────────────────────────


async def _seed_agent_performance_log(conn: asyncpg.Connection) -> None:
    logs = [
        (PERF_LOG_01, AGENT_EXTRACTOR, DOC_01, "AAPL", True, 2500, 0.85, 0, 1200, 800, None, VARIANT_EXTRACTOR, BASE_TS),
        (PERF_LOG_02, AGENT_CLASSIFIER, DOC_08, None, True, 1800, 0.88, 0, 900, 600, None, VARIANT_CLASSIFIER, BASE_TS),
        (PERF_LOG_03, AGENT_THESIS, None, "AAPL", True, 1200, 0.90, 0, 500, 300, None, VARIANT_THESIS, BASE_TS),
    ]
    await conn.executemany(
        """INSERT INTO agent_performance_log
           (id, agent_id, document_id, ticker, success, duration_ms, confidence,
            retry_count, input_tokens, output_tokens, error_message, variant_id, recorded_at)
           VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13)
           ON CONFLICT DO NOTHING""",
        logs,
    )


# ── Risk Configs ──────────────────────────────────────────────


async def _seed_risk_configs(conn: asyncpg.Connection) -> None:
    config = json.dumps({
        "max_portfolio_heat": 0.25,
        "max_single_position_pct": 0.05,
        "max_sector_concentration": 0.30,
        "daily_loss_limit_pct": 0.03,
        "macro_enabled": True,
        "competitive_enabled": True,
    })
    await conn.execute(
        """INSERT INTO risk_configs (id, name, trading_mode, config, active, created_at, updated_at)
           VALUES ($1, $2, $3, $4::jsonb, $5, $6, $7)
           ON CONFLICT DO NOTHING""",
        RISK_CONFIG_01, "inttest-default", "paper", config, True, BASE_TS, BASE_TS,
    )


# ── Audit Events ─────────────────────────────────────────────


async def _seed_audit_events(conn: asyncpg.Connection) -> None:
    events = [
        (AUDIT_01, "order.submitted", "order", ORDER_01, "system",
         json.dumps({"ticker": "AAPL", "side": "buy", "qty": 10}), BASE_TS),
        (AUDIT_02, "order.filled", "order", ORDER_01, "system",
         json.dumps({"ticker": "AAPL", "fill_price": 185.50, "fill_qty": 10}),
         BASE_TS + timedelta(seconds=30)),
        (AUDIT_03, "order.cancelled", "order", ORDER_03, "system",
         json.dumps({"ticker": "XOM", "reason": "user_request"}),
         BASE_TS + timedelta(minutes=5)),
    ]
    await conn.executemany(
        """INSERT INTO audit_events (id, event_type, entity_type, entity_id, actor, data, created_at)
           VALUES ($1, $2, $3, $4, $5, $6::jsonb, $7)
           ON CONFLICT DO NOTHING""",
        events,
    )


# ── Watchlists ────────────────────────────────────────────────


async def _seed_watchlists(conn: asyncpg.Connection) -> None:
    watchlists = [
        (WATCHLIST_01, "Tech Leaders", "Top technology companies", True, BASE_TS, BASE_TS),
        (WATCHLIST_02, "Value Picks", "Undervalued large caps", True, BASE_TS, BASE_TS),
    ]
    await conn.executemany(
        """INSERT INTO watchlists (id, name, description, active, created_at, updated_at)
           VALUES ($1, $2, $3, $4, $5, $6)
           ON CONFLICT DO NOTHING""",
        watchlists,
    )
    members = [
        (WL_MEMBER_01, WATCHLIST_01, COMPANY_AAPL, BASE_TS),
        (WL_MEMBER_02, WATCHLIST_01, COMPANY_MSFT, BASE_TS),
        (WL_MEMBER_03, WATCHLIST_02, COMPANY_JPM, BASE_TS),
    ]
    await conn.executemany(
        """INSERT INTO watchlist_members (id, watchlist_id, company_id, added_at)
           VALUES ($1, $2, $3, $4)
           ON CONFLICT DO NOTHING""",
        members,
    )


# ── Operator Approvals ────────────────────────────────────────


async def _seed_operator_approvals(conn: asyncpg.Connection) -> None:
    approvals = [
        (APPROVAL_PENDING, json.dumps({"ticker": "AAPL", "side": "buy", "qty": 5}),
         REC_01, "AAPL", "buy", 5, 927.50, "pending", RISK_EVAL_01,
         "system", None, None,
         BASE_TS + timedelta(hours=24),  # expires in 24h
         BASE_TS, None, BASE_TS, BASE_TS),
        (APPROVAL_APPROVED, json.dumps({"ticker": "MSFT", "side": "buy", "qty": 3}),
         REC_02, "MSFT", "buy", 3, 1230.00, "approved", None,
         "system", "test-operator", "Approved for paper trading",
         BASE_TS + timedelta(hours=24),
         BASE_TS - timedelta(hours=2), BASE_TS - timedelta(hours=1),
         BASE_TS, BASE_TS),
    ]
    await conn.executemany(
        """INSERT INTO operator_approvals
           (id, order_job, recommendation_id, ticker, side, quantity, estimated_value,
            status, risk_evaluation_id, requested_by, reviewed_by, review_note,
            expires_at, requested_at, reviewed_at, created_at, updated_at)
           VALUES ($1, $2::jsonb, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17)
           ON CONFLICT DO NOTHING""",
        approvals,
    )


# ── Symbol Lockouts ───────────────────────────────────────────


async def _seed_symbol_lockouts(conn: asyncpg.Connection) -> None:
    now = datetime.now(timezone.utc)
    lockouts = [
        (LOCKOUT_ACTIVE, "AAPL", "news_shock", "Earnings volatility cooldown",
         now + timedelta(days=7), now - timedelta(hours=1)),
        (LOCKOUT_EXPIRED, "XOM", "cooldown", "Post-trade cooldown period",
         now - timedelta(days=1), now - timedelta(days=3)),
    ]
    await conn.executemany(
        """INSERT INTO symbol_lockouts (id, ticker, lockout_type, reason, expires_at, created_at)
           VALUES ($1, $2, $3, $4, $5, $6)
           ON CONFLICT DO NOTHING""",
        lockouts,
    )


# ── Notifications ─────────────────────────────────────────────


async def _seed_notifications(conn: asyncpg.Connection) -> None:
    await conn.execute(
        """INSERT INTO notifications
           (id, channel, event_type, message, delivery_status, retry_count, error_message, created_at, delivered_at)
           VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9)
           ON CONFLICT DO NOTHING""",
        NOTIFICATION_01, "email", "order.filled",
        "Order filled: AAPL buy 10 shares at $185.50",
        "delivered", 0, None, BASE_TS, BASE_TS + timedelta(seconds=5),
    )


# ── Ingestion Runs ────────────────────────────────────────────


async def _seed_ingestion_runs(conn: asyncpg.Connection) -> None:
    runs = [
        (INGESTION_RUN_01, SOURCE_AAPL, COMPANY_AAPL, "news", "completed",
         BASE_TS - timedelta(hours=2), BASE_TS - timedelta(hours=1, minutes=55),
         15, 8, None, 0, None),
        (INGESTION_RUN_02, SOURCE_JPM, COMPANY_JPM, "filing", "failed",
         BASE_TS - timedelta(hours=1), None,
         0, 0, "Connection timeout to SEC EDGAR", 2,
         BASE_TS + timedelta(hours=1)),
    ]
    await conn.executemany(
        """INSERT INTO ingestion_runs
           (id, source_id, company_id, source_type, status, started_at, completed_at,
            items_fetched, items_new, error_message, retry_count, next_retry_at)
           VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12)
           ON CONFLICT DO NOTHING""",
        runs,
    )


# ── Saved Queries ─────────────────────────────────────────────


async def _seed_saved_queries(conn: asyncpg.Connection) -> None:
    await conn.execute(
        """INSERT INTO saved_queries (id, name, description, sql_text, created_by, created_at, updated_at)
           VALUES ($1, $2, $3, $4, $5, $6, $7)
           ON CONFLICT DO NOTHING""",
        SAVED_QUERY_01, "Top Recommendations",
        "Shows highest confidence recommendations",
        "SELECT ticker, action, confidence FROM recommendations ORDER BY confidence DESC LIMIT 10",
        "operator", BASE_TS, BASE_TS,
    )


# ── Daily Risk Snapshots ──────────────────────────────────────


async def _seed_daily_risk_snapshots(conn: asyncpg.Connection) -> None:
    await conn.execute(
        """INSERT INTO daily_risk_snapshots
           (id, account_id, snapshot_date, portfolio_value, daily_pnl,
            daily_trade_count, positions_by_sector, created_at, updated_at)
           VALUES ($1, $2, $3, $4, $5, $6, $7::jsonb, $8, $9)
           ON CONFLICT DO NOTHING""",
        RISK_SNAPSHOT_01, "PAPER-001", BASE_DATE, 12500.00, 150.25,
        4, json.dumps({"Technology": 0.45, "Financial Services": 0.30, "Energy": 0.25}),
        BASE_TS, BASE_TS,
    )


# ── Entry point ───────────────────────────────────────────────

if __name__ == "__main__":
    asyncio.run(seed())
