//
//  SavedTrip.swift
//  SportsTime
//
//  SwiftData models for local persistence
//

import Foundation
import SwiftData

@Model
final class SavedTrip {
    @Attribute(.unique) var id: UUID
    var name: String
    var createdAt: Date
    var updatedAt: Date
    var status: String
    var tripData: Data  // Encoded Trip struct
    var gamesData: Data?  // Encoded [UUID: RichGame] dictionary

    @Relationship(deleteRule: .cascade)
    var votes: [TripVote]?

    init(
        id: UUID = UUID(),
        name: String,
        createdAt: Date = Date(),
        updatedAt: Date = Date(),
        status: TripStatus = .planned,
        tripData: Data,
        gamesData: Data? = nil
    ) {
        self.id = id
        self.name = name
        self.createdAt = createdAt
        self.updatedAt = updatedAt
        self.status = status.rawValue
        self.tripData = tripData
        self.gamesData = gamesData
    }

    var trip: Trip? {
        try? JSONDecoder().decode(Trip.self, from: tripData)
    }

    var games: [UUID: RichGame] {
        guard let data = gamesData else { return [:] }
        return (try? JSONDecoder().decode([UUID: RichGame].self, from: data)) ?? [:]
    }

    var tripStatus: TripStatus {
        TripStatus(rawValue: status) ?? .draft
    }

    static func from(_ trip: Trip, games: [UUID: RichGame] = [:], status: TripStatus = .planned) -> SavedTrip? {
        guard let tripData = try? JSONEncoder().encode(trip) else { return nil }
        let gamesData = try? JSONEncoder().encode(games)
        return SavedTrip(
            id: trip.id,
            name: trip.name,
            createdAt: trip.createdAt,
            updatedAt: trip.updatedAt,
            status: status,
            tripData: tripData,
            gamesData: gamesData
        )
    }
}

// MARK: - Trip Vote (Phase 2)

@Model
final class TripVote {
    @Attribute(.unique) var id: UUID
    var tripId: UUID
    var voterId: String
    var voterName: String
    var gameVotes: Data  // [UUID: Bool] encoded
    var routeVotes: Data  // [String: Int] encoded
    var leisurePreference: String
    var createdAt: Date

    init(
        id: UUID = UUID(),
        tripId: UUID,
        voterId: String,
        voterName: String,
        gameVotes: Data,
        routeVotes: Data,
        leisurePreference: LeisureLevel = .moderate,
        createdAt: Date = Date()
    ) {
        self.id = id
        self.tripId = tripId
        self.voterId = voterId
        self.voterName = voterName
        self.gameVotes = gameVotes
        self.routeVotes = routeVotes
        self.leisurePreference = leisurePreference.rawValue
        self.createdAt = createdAt
    }
}

// MARK: - User Preferences

@Model
final class UserPreferences {
    @Attribute(.unique) var id: UUID
    var defaultSports: Data  // [Sport] encoded
    var defaultTravelMode: String
    var defaultLeisureLevel: String
    var defaultLodgingType: String
    var homeLocation: Data?  // LocationInput encoded
    var needsEVCharging: Bool
    var numberOfDrivers: Int
    var maxDrivingHours: Double?

    init(
        id: UUID = UUID(),
        defaultSports: [Sport] = Sport.supported,
        defaultTravelMode: TravelMode = .drive,
        defaultLeisureLevel: LeisureLevel = .moderate,
        defaultLodgingType: LodgingType = .hotel,
        homeLocation: LocationInput? = nil,
        needsEVCharging: Bool = false,
        numberOfDrivers: Int = 1,
        maxDrivingHours: Double? = nil
    ) {
        self.id = id
        self.defaultSports = (try? JSONEncoder().encode(defaultSports)) ?? Data()
        self.defaultTravelMode = defaultTravelMode.rawValue
        self.defaultLeisureLevel = defaultLeisureLevel.rawValue
        self.defaultLodgingType = defaultLodgingType.rawValue
        self.homeLocation = try? JSONEncoder().encode(homeLocation)
        self.needsEVCharging = needsEVCharging
        self.numberOfDrivers = numberOfDrivers
        self.maxDrivingHours = maxDrivingHours
    }

    var sports: [Sport] {
        (try? JSONDecoder().decode([Sport].self, from: defaultSports)) ?? Sport.supported
    }

    var travelMode: TravelMode {
        TravelMode(rawValue: defaultTravelMode) ?? .drive
    }

    var leisureLevel: LeisureLevel {
        LeisureLevel(rawValue: defaultLeisureLevel) ?? .moderate
    }

    var lodgingType: LodgingType {
        LodgingType(rawValue: defaultLodgingType) ?? .hotel
    }

    var home: LocationInput? {
        guard let data = homeLocation else { return nil }
        return try? JSONDecoder().decode(LocationInput.self, from: data)
    }
}

// MARK: - Cached Schedule

@Model
final class CachedSchedule {
    @Attribute(.unique) var id: UUID
    var sport: String
    var season: String
    var lastUpdated: Date
    var gamesData: Data  // [Game] encoded
    var teamsData: Data  // [Team] encoded
    var stadiumsData: Data  // [Stadium] encoded

    init(
        id: UUID = UUID(),
        sport: Sport,
        season: String,
        lastUpdated: Date = Date(),
        games: [Game],
        teams: [Team],
        stadiums: [Stadium]
    ) {
        self.id = id
        self.sport = sport.rawValue
        self.season = season
        self.lastUpdated = lastUpdated
        self.gamesData = (try? JSONEncoder().encode(games)) ?? Data()
        self.teamsData = (try? JSONEncoder().encode(teams)) ?? Data()
        self.stadiumsData = (try? JSONEncoder().encode(stadiums)) ?? Data()
    }

    var games: [Game] {
        (try? JSONDecoder().decode([Game].self, from: gamesData)) ?? []
    }

    var teams: [Team] {
        (try? JSONDecoder().decode([Team].self, from: teamsData)) ?? []
    }

    var stadiums: [Stadium] {
        (try? JSONDecoder().decode([Stadium].self, from: stadiumsData)) ?? []
    }

    var isStale: Bool {
        let staleThreshold: TimeInterval = 24 * 60 * 60  // 24 hours
        return Date().timeIntervalSince(lastUpdated) > staleThreshold
    }
}
