//
//  Progress.swift
//  SportsTime
//
//  Domain models for tracking stadium visit progress and achievements.
//
//  - Expected Behavior:
//    - completionPercentage = (visited / total) * 100, returns 0 when total is 0
//    - progressFraction = visited / total, returns 0 when total is 0
//    - isComplete = total > 0 AND visited >= total
//    - StadiumVisitStatus.latestVisit returns visit with max date
//    - StadiumVisitStatus.firstVisit returns visit with min date
//
//  - Invariants:
//    - completionPercentage is in range [0, 100]
//    - progressFraction is in range [0, 1]
//    - isComplete can only be true if totalStadiums > 0
//    - visitCount == 0 for notVisited status
//

import Foundation
import SwiftUI

// MARK: - League Progress

/// Progress tracking for a single sport/league
struct LeagueProgress: Identifiable {
    let sport: Sport
    let totalStadiums: Int
    let visitedStadiums: Int
    let stadiumsVisited: [Stadium]
    let stadiumsRemaining: [Stadium]

    var id: String { sport.rawValue }

    var completionPercentage: Double {
        guard totalStadiums > 0 else { return 0 }
        return Double(visitedStadiums) / Double(totalStadiums) * 100
    }

    var isComplete: Bool {
        totalStadiums > 0 && visitedStadiums >= totalStadiums
    }

    var progressFraction: Double {
        guard totalStadiums > 0 else { return 0 }
        return Double(visitedStadiums) / Double(totalStadiums)
    }

    var progressDescription: String {
        "\(visitedStadiums)/\(totalStadiums)"
    }
}

// MARK: - Division Progress

/// Progress tracking for a single division
struct DivisionProgress: Identifiable {
    let division: Division
    let totalStadiums: Int
    let visitedStadiums: Int
    let stadiumsVisited: [Stadium]
    let stadiumsRemaining: [Stadium]

    var id: String { division.id }

    var completionPercentage: Double {
        guard totalStadiums > 0 else { return 0 }
        return Double(visitedStadiums) / Double(totalStadiums) * 100
    }

    var isComplete: Bool {
        totalStadiums > 0 && visitedStadiums >= totalStadiums
    }

    var progressFraction: Double {
        guard totalStadiums > 0 else { return 0 }
        return Double(visitedStadiums) / Double(totalStadiums)
    }
}

// MARK: - Conference Progress

/// Progress tracking for a conference
struct ConferenceProgress: Identifiable {
    let conference: Conference
    let totalStadiums: Int
    let visitedStadiums: Int
    let divisionProgress: [DivisionProgress]

    var id: String { conference.id }

    var completionPercentage: Double {
        guard totalStadiums > 0 else { return 0 }
        return Double(visitedStadiums) / Double(totalStadiums) * 100
    }

    var isComplete: Bool {
        totalStadiums > 0 && visitedStadiums >= totalStadiums
    }
}

// MARK: - Overall Progress

/// Combined progress across all sports
struct OverallProgress {
    let leagueProgress: [LeagueProgress]
    let totalVisits: Int
    let uniqueStadiumsVisited: Int
    let totalStadiumsAcrossLeagues: Int
    let achievementsEarned: Int
    let totalAchievements: Int

    var overallPercentage: Double {
        guard totalStadiumsAcrossLeagues > 0 else { return 0 }
        return Double(uniqueStadiumsVisited) / Double(totalStadiumsAcrossLeagues) * 100
    }

    /// Progress by sport
    func progress(for sport: Sport) -> LeagueProgress? {
        leagueProgress.first { $0.sport == sport }
    }
}

// MARK: - Visit Summary

/// Summary of a stadium visit for display
struct VisitSummary: Identifiable {
    let id: UUID
    let stadium: Stadium
    let visitDate: Date
    let visitType: VisitType
    let sport: Sport
    let homeTeamName: String?
    let awayTeamName: String?
    let score: String?
    let photoCount: Int
    let notes: String?

    /// Combined matchup for backwards compatibility
    var matchup: String? {
        guard let home = homeTeamName, let away = awayTeamName else { return nil }
        return "\(away) @ \(home)"
    }

    var dateDescription: String {
        let formatter = DateFormatter()
        formatter.dateStyle = .medium
        return formatter.string(from: visitDate)
    }

    var shortDateDescription: String {
        let formatter = DateFormatter()
        formatter.dateFormat = "MMM d, yyyy"
        return formatter.string(from: visitDate)
    }
}

// MARK: - Stadium Visit Status

/// Status of a stadium (visited or not, with visit info if applicable)
enum StadiumVisitStatus {
    case visited(visits: [VisitSummary])
    case notVisited

    var isVisited: Bool {
        if case .visited = self {
            return true
        }
        return false
    }

    var visitCount: Int {
        if case .visited(let visits) = self {
            return visits.count
        }
        return 0
    }

    var latestVisit: VisitSummary? {
        if case .visited(let visits) = self {
            return visits.max(by: { $0.visitDate < $1.visitDate })
        }
        return nil
    }

    var firstVisit: VisitSummary? {
        if case .visited(let visits) = self {
            return visits.min(by: { $0.visitDate < $1.visitDate })
        }
        return nil
    }
}

// MARK: - Progress Card Data

/// Data for generating shareable progress cards
struct ProgressCardData {
    let sport: Sport
    let progress: LeagueProgress
    let username: String?
    let includeMap: Bool
    let showDetailedStats: Bool

    var title: String {
        "\(sport.displayName) Stadium Quest"
    }

    var subtitle: String {
        "\(progress.visitedStadiums) of \(progress.totalStadiums) Stadiums"
    }

    var percentageText: String {
        String(format: "%.0f%%", progress.completionPercentage)
    }
}

// MARK: - Progress Card Options

struct ProgressCardOptions {
    var includeUsername: Bool = true
    var username: String?
    var includeMapSnapshot: Bool = true
    var includeStats: Bool = true
    var cardStyle: CardStyle = .dark

    enum CardStyle {
        case dark
        case light

        var backgroundColor: Color {
            switch self {
            case .dark: return Color(hex: "1A1A2E")
            case .light: return Color.white
            }
        }

        var textColor: Color {
            switch self {
            case .dark: return .white
            case .light: return Color(hex: "1A1A2E")
            }
        }

        var secondaryTextColor: Color {
            switch self {
            case .dark: return Color(hex: "B8B8D1")
            case .light: return Color(hex: "666666")
            }
        }
    }
}
