"""Shared fixtures for pyfortis tests."""

from __future__ import annotations

import pytest

from pyfortis._types import (
    BreachAction,
    CircuitBreakerSpec,
    CircuitBreakerType,
    EscalationPolicy,
    Exposure,
    LimitScope,
    LimitSpec,
    LimitType,
    MetricSpec,
    MetricType,
    Order,
    Position,
    Severity,
    Side,
)


@pytest.fixture
def sample_order() -> Order:
    return Order(
        order_id="test-001",
        instrument="AAPL",
        side=Side.BUY,
        quantity=100,
        price=150.0,
        portfolio="default",
        sector="technology",
    )


@pytest.fixture
def sample_position() -> Position:
    return Position(
        instrument="AAPL",
        quantity=5000,
        avg_price=145.0,
        current_price=150.0,
        portfolio="default",
        sector="technology",
    )


@pytest.fixture
def sample_positions(sample_position: Position) -> dict[str, Position]:
    return {
        "AAPL": sample_position,
        "GOOGL": Position(
            instrument="GOOGL",
            quantity=200,
            avg_price=2800.0,
            current_price=2850.0,
            sector="technology",
        ),
    }


@pytest.fixture
def sample_exposures(sample_positions: dict[str, Position]) -> dict[str, Exposure]:
    return {
        inst: Exposure.from_position(pos)
        for inst, pos in sample_positions.items()
    }


@pytest.fixture
def position_limit() -> LimitSpec:
    return LimitSpec(
        name="max_position_size",
        type=LimitType.POSITION,
        scope=LimitScope.INSTRUMENT,
        params={"max_long": 10000, "max_short": 5000},
        severity=Severity.CRITICAL,
    )


@pytest.fixture
def concentration_limit() -> LimitSpec:
    return LimitSpec(
        name="portfolio_concentration",
        type=LimitType.CONCENTRATION,
        scope=LimitScope.PORTFOLIO,
        params={"max_single_asset_pct": 0.15, "max_sector_pct": 0.30},
        severity=Severity.WARNING,
    )


@pytest.fixture
def price_tolerance_limit() -> LimitSpec:
    return LimitSpec(
        name="fat_finger_check",
        type=LimitType.PRICE_TOLERANCE,
        scope=LimitScope.ORDER,
        params={"max_deviation_pct": 0.05},
        severity=Severity.CRITICAL,
    )


@pytest.fixture
def sample_limits(
    position_limit: LimitSpec,
    concentration_limit: LimitSpec,
    price_tolerance_limit: LimitSpec,
) -> list[LimitSpec]:
    return [position_limit, concentration_limit, price_tolerance_limit]


@pytest.fixture
def var_metric() -> MetricSpec:
    return MetricSpec(
        name="portfolio_var",
        type=MetricType.VAR,
        params={"method": "historical", "confidence": 0.95, "horizon_days": 1},
    )


@pytest.fixture
def drawdown_metric() -> MetricSpec:
    return MetricSpec(
        name="max_drawdown",
        type=MetricType.DRAWDOWN,
        params={"window": "20d", "threshold": 0.10},
        severity=Severity.WARNING,
    )


@pytest.fixture
def sample_metrics(var_metric: MetricSpec, drawdown_metric: MetricSpec) -> list[MetricSpec]:
    return [var_metric, drawdown_metric]


@pytest.fixture
def daily_pnl_breaker() -> CircuitBreakerSpec:
    return CircuitBreakerSpec(
        name="daily_loss_limit",
        type=CircuitBreakerType.DAILY_PNL,
        params={"max_loss": -50000},
        action=BreachAction.HALT_TRADING,
        cooldown="1h",
    )


@pytest.fixture
def sample_escalation() -> EscalationPolicy:
    return EscalationPolicy(
        default_action=BreachAction.LOG,
        escalation={
            Severity.WARNING: [BreachAction.LOG, BreachAction.NOTIFY],
            Severity.CRITICAL: [
                BreachAction.LOG,
                BreachAction.NOTIFY,
                BreachAction.BLOCK_ORDER,
            ],
            Severity.KILL: [
                BreachAction.LOG,
                BreachAction.NOTIFY,
                BreachAction.BLOCK_ORDER,
                BreachAction.FLATTEN_POSITIONS,
            ],
        },
    )


@pytest.fixture
def sample_returns() -> list[float]:
    return [0.01, -0.02, 0.015, -0.005, 0.008, -0.01, 0.02, -0.03, 0.005, 0.01]


@pytest.fixture
def sample_config() -> dict:
    return {
        "meta": {
            "version": "1.0.0",
            "engine_name": "test_engine",
            "strict_mode": True,
        },
        "limits": [
            {
                "name": "max_position_size",
                "type": "position",
                "scope": "instrument",
                "params": {"max_long": 10000, "max_short": 5000},
                "severity": "CRITICAL",
            },
            {
                "name": "portfolio_concentration",
                "type": "concentration",
                "scope": "portfolio",
                "params": {"max_single_asset_pct": 0.15, "max_sector_pct": 0.30},
                "severity": "WARNING",
            },
        ],
        "metrics": [
            {
                "name": "portfolio_var",
                "type": "var",
                "params": {"confidence": 0.95},
            },
        ],
        "circuit_breakers": [
            {
                "name": "daily_loss_limit",
                "type": "daily_pnl",
                "params": {"max_loss": -50000},
                "action": "halt_trading",
                "cooldown": "1h",
            },
        ],
        "breach_policy": {
            "default_action": "log",
            "escalation": {
                "WARNING": ["log", "notify"],
                "CRITICAL": ["log", "notify", "block_order"],
            },
        },
    }
