use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
use serde_json as json;
use uuid::Uuid;

use crate::{
    events::{
        EventManifestSnapshot, EventMediaSnapshot, EventSnapshot, MarketSnapshot, OutcomeSnapshot,
    },
    markets::{OddsVersionSnapshot, OutcomeOddsSnapshot},
    settlement::SettlementSnapshot,
};

#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct SettlementFixture {
    pub event_id: Uuid,
    pub settlement: SettlementSnapshot,
}

#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct SampleStudyFixture {
    pub manifest: EventManifestSnapshot,
    pub odds_versions: Vec<OddsVersionSnapshot>,
    pub settlement: SettlementFixture,
}

pub fn load_sample_study_fixture() -> SampleStudyFixture {
    let raw = include_str!("../../../fixtures/manifests/sample_event.json");
    json::from_str(raw).expect("valid sample study fixture")
}

pub fn build_sample_study_fixture() -> SampleStudyFixture {
    let event_id = Uuid::parse_str("11111111-1111-1111-1111-111111111111").expect("valid uuid");
    let market_id = Uuid::parse_str("22222222-2222-2222-2222-222222222222").expect("valid uuid");
    let odds_version_id =
        Uuid::parse_str("66666666-6666-6666-6666-666666666666").expect("valid uuid");
    let lock_at = parse_ts("2099-01-01T00:10:00Z");
    let settle_at = parse_ts("2099-01-01T00:25:00Z");
    let created_at = parse_ts("2099-01-01T00:00:00Z");

    let home_outcome_id =
        Uuid::parse_str("44444444-4444-4444-4444-444444444444").expect("valid uuid");
    let away_outcome_id =
        Uuid::parse_str("55555555-5555-5555-5555-555555555555").expect("valid uuid");

    let event = EventSnapshot {
        id: event_id,
        sport_type: "football".to_string(),
        source_ref: "sample-event-001".to_string(),
        title_en: "Late winner chance".to_string(),
        title_sv: "Möjlighet till segermål".to_string(),
        status: "prefetch_ready".to_string(),
        preview_start_ms: 0,
        preview_end_ms: 45_000,
        reveal_start_ms: 50_000,
        reveal_end_ms: 90_000,
        lock_at,
        settle_at,
    };

    let media = EventMediaSnapshot {
        id: Uuid::parse_str("33333333-3333-3333-3333-333333333333").expect("valid uuid"),
        event_id,
        media_type: "hls_main".to_string(),
        hls_master_url: "https://cdn.example.com/hermes/sample-event/master.m3u8".to_string(),
        poster_url: Some("https://cdn.example.com/hermes/sample-event/poster.jpg".to_string()),
        duration_ms: 90_000,
        preview_start_ms: 0,
        preview_end_ms: 45_000,
        reveal_start_ms: 50_000,
        reveal_end_ms: 90_000,
    };

    let outcomes = vec![
        OutcomeSnapshot {
            id: home_outcome_id,
            market_id,
            outcome_code: "home".to_string(),
            label_key: "outcome.home".to_string(),
            sort_order: 1,
        },
        OutcomeSnapshot {
            id: away_outcome_id,
            market_id,
            outcome_code: "away".to_string(),
            label_key: "outcome.away".to_string(),
            sort_order: 2,
        },
    ];

    let market = MarketSnapshot {
        id: market_id,
        event_id,
        question_key: "market.sample.winner".to_string(),
        market_type: "winner".to_string(),
        status: "open".to_string(),
        lock_at,
        settlement_rule_key: "settle_on_match_winner".to_string(),
        outcomes,
    };

    let odds_version = OddsVersionSnapshot {
        id: odds_version_id,
        market_id,
        version_no: 1,
        created_at,
        is_current: true,
        odds: vec![
            OutcomeOddsSnapshot {
                id: Uuid::parse_str("77777777-7777-7777-7777-777777777777").expect("valid uuid"),
                odds_version_id,
                outcome_id: home_outcome_id,
                decimal_odds: 1.85,
                fractional_num: 17,
                fractional_den: 20,
            },
            OutcomeOddsSnapshot {
                id: Uuid::parse_str("88888888-8888-8888-8888-888888888888").expect("valid uuid"),
                odds_version_id,
                outcome_id: away_outcome_id,
                decimal_odds: 2.05,
                fractional_num: 21,
                fractional_den: 20,
            },
        ],
    };

    let settlement = SettlementFixture {
        event_id,
        settlement: SettlementSnapshot {
            id: Uuid::parse_str("99999999-9999-9999-9999-999999999999").expect("valid uuid"),
            market_id,
            settled_at: settle_at,
            winning_outcome_id: home_outcome_id,
        },
    };

    SampleStudyFixture {
        manifest: EventManifestSnapshot {
            event,
            media: vec![media],
            markets: vec![market],
        },
        odds_versions: vec![odds_version],
        settlement,
    }
}

fn parse_ts(value: &str) -> DateTime<Utc> {
    DateTime::parse_from_rfc3339(value)
        .expect("valid timestamp")
        .with_timezone(&Utc)
}
