//
//  SessionStatusLive.swift

import SwiftUI
import WidgetKit

struct ClimbingStatsProvider: TimelineProvider {
    typealias Entry = ClimbingStatsEntry

    func placeholder(in context: Context) -> ClimbingStatsEntry {
        ClimbingStatsEntry(
            date: Date(),
            weeklyAttempts: 42,
            weeklySessions: 5,
            currentStreak: 3,
            favoriteGym: "Summit Climbing"
        )
    }

    func getSnapshot(in context: Context, completion: @escaping (ClimbingStatsEntry) -> Void) {
        let entry = ClimbingStatsEntry(
            date: Date(),
            weeklyAttempts: 42,
            weeklySessions: 5,
            currentStreak: 3,
            favoriteGym: "Summit Climbing"
        )
        completion(entry)
    }

    func getTimeline(
        in context: Context, completion: @escaping (Timeline<ClimbingStatsEntry>) -> Void
    ) {
        let currentDate = Date()
        let stats = loadClimbingStats()

        let entry = ClimbingStatsEntry(
            date: currentDate,
            weeklyAttempts: stats.weeklyAttempts,
            weeklySessions: stats.weeklySessions,
            currentStreak: stats.currentStreak,
            favoriteGym: stats.favoriteGym
        )

        // Update every hour
        let nextUpdate = Calendar.current.date(byAdding: .hour, value: 1, to: currentDate)!
        let timeline = Timeline(entries: [entry], policy: .after(nextUpdate))
        completion(timeline)
    }

    private func loadClimbingStats() -> ClimbingStats {
        let userDefaults = UserDefaults(suiteName: "group.com.atridad.Ascently")

        // Load attempts from UserDefaults
        guard let attemptsData = userDefaults?.data(forKey: "ascently_attempts"),
            let attempts = try? JSONDecoder().decode([WidgetAttempt].self, from: attemptsData)
        else {
            return ClimbingStats(
                weeklyAttempts: 0, weeklySessions: 0, currentStreak: 0, favoriteGym: "No Data")
        }

        // Load sessions for streak calculation
        let sessionsData = (userDefaults?.data(forKey: "ascently_sessions"))!
        let sessions = (try? JSONDecoder().decode([WidgetSession].self, from: sessionsData)) ?? []

        // Load gyms for favorite gym name
        let gymsData = (userDefaults?.data(forKey: "ascently_gyms"))!
        let gyms = (try? JSONDecoder().decode([WidgetGym].self, from: gymsData)) ?? []

        let calendar = Calendar.current
        let now = Date()
        let weekAgo = calendar.date(byAdding: .day, value: -7, to: now)!
        _ = calendar.startOfDay(for: now)

        // Calculate weekly attempts
        let weeklyAttempts = attempts.filter { attempt in
            attempt.timestamp >= weekAgo
        }.count

        // Calculate weekly sessions
        let weeklySessions = sessions.filter { session in
            session.date >= weekAgo && session.status == "COMPLETED"
        }.count

        // Calculate current streak (consecutive days with sessions)
        let currentStreak = calculateStreak(sessions: sessions)

        // Find favorite gym
        let favoriteGym = findFavoriteGym(sessions: sessions, gyms: gyms)

        return ClimbingStats(
            weeklyAttempts: weeklyAttempts,
            weeklySessions: weeklySessions,
            currentStreak: currentStreak,
            favoriteGym: favoriteGym
        )
    }

    private func calculateStreak(sessions: [WidgetSession]) -> Int {
        let calendar = Calendar.current
        let completedSessions = sessions.filter { $0.status == "COMPLETED" }
            .sorted { $0.date > $1.date }

        guard !completedSessions.isEmpty else { return 0 }

        var streak = 0
        var currentDate = calendar.startOfDay(for: Date())

        for session in completedSessions {
            let sessionDate = calendar.startOfDay(for: session.date)

            if sessionDate == currentDate {
                streak += 1
                currentDate = calendar.date(byAdding: .day, value: -1, to: currentDate)!
            } else if sessionDate == calendar.date(byAdding: .day, value: -1, to: currentDate) {
                streak += 1
                currentDate = calendar.date(byAdding: .day, value: -1, to: currentDate)!
            } else {
                break
            }
        }

        return streak
    }

    private func findFavoriteGym(sessions: [WidgetSession], gyms: [WidgetGym]) -> String {
        let gymCounts = Dictionary(grouping: sessions, by: { $0.gymId })
            .mapValues { $0.count }

        guard let mostUsedGymId = gymCounts.max(by: { $0.value < $1.value })?.key,
            let gym = gyms.first(where: { $0.id == mostUsedGymId })
        else {
            return "No Data"
        }

        return gym.name
    }
}

struct ClimbingStatsEntry: TimelineEntry {
    let date: Date
    let weeklyAttempts: Int
    let weeklySessions: Int
    let currentStreak: Int
    let favoriteGym: String
}

struct ClimbingStats {
    let weeklyAttempts: Int
    let weeklySessions: Int
    let currentStreak: Int
    let favoriteGym: String
}

struct SessionStatusLiveEntryView: View {
    var entry: ClimbingStatsEntry
    @Environment(\.widgetFamily) var family

    var body: some View {
        switch family {
        case .systemSmall:
            SmallWidgetView(entry: entry)
        case .systemMedium:
            MediumWidgetView(entry: entry)
        default:
            SmallWidgetView(entry: entry)
        }
    }
}

struct SmallWidgetView: View {
    let entry: ClimbingStatsEntry

    var body: some View {
        VStack(spacing: 12) {
            // Header
            HStack {
                if let uiImage = UIImage(named: "AppIcon") {
                    Image(uiImage: uiImage)
                        .resizable()
                        .frame(width: 24, height: 24)
                        .clipShape(RoundedRectangle(cornerRadius: 6))
                } else {
                    Image(systemName: "figure.climbing")
                        .font(.title2)
                        .foregroundColor(.accentColor)
                }
                Spacer()
                Text("Weekly")
                    .font(.caption)
                    .foregroundColor(.secondary)
            }

            Spacer()

            // Main stats - weekly attempts and sessions
            VStack(spacing: 16) {
                HStack(spacing: 8) {
                    Image(systemName: "hand.raised.fill")
                        .foregroundColor(.green)
                        .font(.title2)
                    Text("\(entry.weeklyAttempts)")
                        .font(.title)
                        .fontWeight(.bold)
                        .foregroundColor(.primary)
                }

                HStack(spacing: 8) {
                    Image(systemName: "play.fill")
                        .foregroundColor(.blue)
                        .font(.title2)
                    Text("\(entry.weeklySessions)")
                        .font(.title)
                        .fontWeight(.bold)
                        .foregroundColor(.primary)
                }
            }

            Spacer()
        }
        .padding()
    }
}

struct MediumWidgetView: View {
    let entry: ClimbingStatsEntry

    var body: some View {
        VStack(spacing: 16) {
            // Header
            HStack {
                HStack(spacing: 6) {
                    if let uiImage = UIImage(named: "AppIcon") {
                        Image(uiImage: uiImage)
                            .resizable()
                            .frame(width: 24, height: 24)
                            .clipShape(RoundedRectangle(cornerRadius: 6))
                    } else {
                        Image(systemName: "figure.climbing")
                            .font(.title2)
                            .foregroundColor(.accentColor)
                    }
                    Text("Weekly")
                        .font(.headline)
                        .fontWeight(.semibold)
                }
                Spacer()
            }

            // Main stats row - weekly attempts and sessions
            HStack(spacing: 40) {
                VStack(spacing: 8) {
                    HStack(spacing: 8) {
                        Image(systemName: "hand.raised.fill")
                            .foregroundColor(.green)
                            .font(.title2)
                        Text("\(entry.weeklyAttempts)")
                            .font(.title)
                            .fontWeight(.bold)
                            .foregroundColor(.primary)
                    }
                }

                VStack(spacing: 8) {
                    HStack(spacing: 8) {
                        Image(systemName: "play.fill")
                            .foregroundColor(.blue)
                            .font(.title2)
                        Text("\(entry.weeklySessions)")
                            .font(.title)
                            .fontWeight(.bold)
                            .foregroundColor(.primary)
                    }
                }
            }

            Spacer()
        }
        .padding()
    }
}

struct SessionStatusLive: Widget {
    let kind: String = "SessionStatusLive"

    var body: some WidgetConfiguration {
        StaticConfiguration(kind: kind, provider: ClimbingStatsProvider()) { entry in
            SessionStatusLiveEntryView(entry: entry)
                .containerBackground(.fill.tertiary, for: .widget)
        }
        .configurationDisplayName("Climbing Stats")
        .description("Track your climbing attempts and streaks")
        .supportedFamilies([.systemSmall, .systemMedium])
    }
}

// Simplified data models for widget use
struct WidgetAttempt: Codable {
    let id: String
    let sessionId: String
    let problemId: String
    let timestamp: Date
    let result: String
}

struct WidgetSession: Codable {
    let id: String
    let gymId: String
    let date: Date
    let status: String
}

struct WidgetGym: Codable {
    let id: String
    let name: String
}

#Preview(as: .systemSmall) {
    SessionStatusLive()
} timeline: {
    ClimbingStatsEntry(
        date: .now,
        weeklyAttempts: 42,
        weeklySessions: 5,
        currentStreak: 3,
        favoriteGym: "Summit Climbing"
    )
    ClimbingStatsEntry(
        date: .now,
        weeklyAttempts: 58,
        weeklySessions: 8,
        currentStreak: 5,
        favoriteGym: "Boulder Zone"
    )
}
