import SwiftUI

struct AnalyticsView: View {
    @EnvironmentObject var dataManager: ClimbingDataManager
    @EnvironmentObject var themeManager: ThemeManager

    var body: some View {
        NavigationStack {
            ScrollView {
                LazyVStack(spacing: 20) {
                    OverallStatsSection()

                    ProgressChartSection()

                    HStack(spacing: 16) {
                        FavoriteGymSection()

                        RecentActivitySection()
                    }
                }
                .padding()
            }
            .navigationTitle("Analytics")
            .toolbar {
                ToolbarItem(placement: .navigationBarTrailing) {
                    if dataManager.isSyncing {
                        HStack(spacing: 2) {
                            ProgressView()
                                .progressViewStyle(CircularProgressViewStyle(tint: themeManager.accentColor))
                                .scaleEffect(0.6)
                        }
                        .padding(.horizontal, 6)
                        .padding(.vertical, 3)
                        .background(
                            Circle()
                                .fill(.regularMaterial)
                        )
                        .transition(.scale.combined(with: .opacity))
                        .animation(
                            .easeInOut(duration: 0.2), value: dataManager.isSyncing
                        )
                    }
                }
            }
        }
    }
}

struct OverallStatsSection: View {
    @EnvironmentObject var dataManager: ClimbingDataManager
    @EnvironmentObject var themeManager: ThemeManager

    var body: some View {
        VStack(alignment: .leading, spacing: 16) {
            Text("Overall Stats")
                .font(.title2)
                .fontWeight(.bold)

            LazyVGrid(columns: Array(repeating: GridItem(.flexible()), count: 2), spacing: 16) {
                StatCard(
                    title: "Sessions",
                    value: "\(dataManager.completedSessions().count)",
                    icon: "play.fill",
                    color: themeManager.accentColor
                )

                StatCard(
                    title: "Problems",
                    value: "\(dataManager.problems.count)",
                    icon: "star.fill",
                    color: .orange
                )

                StatCard(
                    title: "Attempts",
                    value: "\(dataManager.totalAttempts())",
                    icon: "hand.raised.fill",
                    color: .green
                )

                StatCard(
                    title: "Gyms",
                    value: "\(dataManager.gyms.count)",
                    icon: "location.fill",
                    color: .purple
                )
            }
        }
        .padding()
        .background(
            RoundedRectangle(cornerRadius: 16)
                .fill(.regularMaterial)
        )
    }
}

struct StatCard: View {
    let title: String
    let value: String
    let icon: String
    let color: Color

    var body: some View {
        VStack(spacing: 8) {
            Image(systemName: icon)
                .font(.title2)
                .foregroundColor(color)

            Text(value)
                .font(.title)
                .fontWeight(.bold)
                .foregroundColor(.primary)

            Text(title)
                .font(.caption)
                .foregroundColor(.secondary)
        }
        .frame(maxWidth: .infinity)
        .padding()
        .background(
            RoundedRectangle(cornerRadius: 12)
                .fill(Color(uiColor: .secondarySystemGroupedBackground))
                .shadow(color: .black.opacity(0.05), radius: 2, x: 0, y: 1)
        )
    }
}

struct ProgressChartSection: View {
    @EnvironmentObject var dataManager: ClimbingDataManager
    @EnvironmentObject var themeManager: ThemeManager
    @State private var selectedSystem: DifficultySystem = .vScale
    @State private var showAllTime: Bool = true
    @State private var cachedGradeCountData: [GradeCount] = []
    @State private var lastCalculationDate: Date = Date.distantPast
    @State private var lastDataHash: Int = 0

    private var gradeCountData: [GradeCount] {
        let currentHash =
            dataManager.problems.count + dataManager.attempts.count + (showAllTime ? 1 : 0)
        let now = Date()

        // Recalculate only if data changed or cache is older than 30 seconds
        if currentHash != lastDataHash || now.timeIntervalSince(lastCalculationDate) > 30 {
            let newData = calculateGradeCounts()
            DispatchQueue.main.async {
                self.cachedGradeCountData = newData
                self.lastCalculationDate = now
                self.lastDataHash = currentHash
            }
        }

        return cachedGradeCountData.isEmpty ? calculateGradeCounts() : cachedGradeCountData
    }

    private var usedSystems: [DifficultySystem] {
        let uniqueSystems = Set(gradeCountData.map { $0.difficultySystem })
        return uniqueSystems.sorted {
            let order: [DifficultySystem] = [.vScale, .font, .yds, .custom]
            let firstIndex = order.firstIndex(of: $0) ?? order.count
            let secondIndex = order.firstIndex(of: $1) ?? order.count
            return firstIndex < secondIndex
        }
    }

    var body: some View {
        VStack(alignment: .leading, spacing: 16) {
            Text("Grade Distribution")
                .font(.title2)
                .fontWeight(.bold)

            // Toggles section
            HStack {
                // Time period toggle
                HStack(spacing: 8) {
                    Button(action: {
                        showAllTime = true
                    }) {
                        Text("All Time")
                            .font(.caption)
                            .fontWeight(.medium)
                            .padding(.horizontal, 8)
                            .padding(.vertical, 4)
                            .background(
                                RoundedRectangle(cornerRadius: 6)
                                    .fill(showAllTime ? themeManager.accentColor : .clear)
                                    .stroke(themeManager.accentColor.opacity(0.3), lineWidth: 1)
                            )
                            .foregroundColor(showAllTime ? themeManager.contrastingTextColor : themeManager.accentColor)
                    }

                    Button(action: {
                        showAllTime = false
                    }) {
                        Text("7 Days")
                            .font(.caption)
                            .fontWeight(.medium)
                            .padding(.horizontal, 8)
                            .padding(.vertical, 4)
                            .background(
                                RoundedRectangle(cornerRadius: 6)
                                    .fill(!showAllTime ? themeManager.accentColor : .clear)
                                    .stroke(themeManager.accentColor.opacity(0.3), lineWidth: 1)
                            )
                            .foregroundColor(!showAllTime ? themeManager.contrastingTextColor : themeManager.accentColor)
                    }
                }

                Spacer()

                // Scale selector (only show if multiple systems)
                if usedSystems.count > 1 {
                    Menu {
                        ForEach(usedSystems, id: \.self) { system in
                            Button(action: {
                                selectedSystem = system
                            }) {
                                HStack {
                                    Text(system.displayName)
                                    if selectedSystem == system {
                                        Spacer()
                                        Image(systemName: "checkmark")
                                            .foregroundColor(themeManager.accentColor)
                                    }
                                }
                            }
                        }
                    } label: {
                        HStack(spacing: 4) {
                            Text(selectedSystem.displayName)
                                .font(.subheadline)
                                .fontWeight(.medium)
                            Image(systemName: "chevron.down")
                                .font(.caption)
                        }
                        .padding(.horizontal, 12)
                        .padding(.vertical, 6)
                        .background(
                            RoundedRectangle(cornerRadius: 8)
                                .fill(themeManager.accentColor.opacity(0.1))
                                .stroke(themeManager.accentColor.opacity(0.3), lineWidth: 1)
                        )
                        .foregroundColor(themeManager.accentColor)
                    }
                }
            }

            let filteredData = gradeCountData.filter { $0.difficultySystem == selectedSystem }

            if !filteredData.isEmpty {
                BarChartView(data: filteredData)
                    .frame(height: 200)

                Text("Successful climbs by grade")
                    .font(.caption)
                    .foregroundColor(.secondary)
            } else {
                VStack(spacing: 8) {
                    Image(systemName: "chart.bar")
                        .font(.title)
                        .foregroundColor(.secondary)

                    Text("No data available.")
                        .font(.subheadline)
                        .foregroundColor(.secondary)
                }
                .frame(height: 200)
                .frame(maxWidth: .infinity)
            }
        }
        .padding()
        .background(
            RoundedRectangle(cornerRadius: 16)
                .fill(.regularMaterial)
        )
        .onAppear {
            if let firstSystem = usedSystems.first {
                selectedSystem = firstSystem
            }
        }
    }

    private func calculateGradeCounts() -> [GradeCount] {
        let problems = dataManager.problems
        let attempts = dataManager.attempts

        // Filter attempts by time period
        let filteredAttempts: [Attempt]
        if showAllTime {
            filteredAttempts = attempts.filter { $0.result.isSuccessful }
        } else {
            let sevenDaysAgo =
                Calendar.current.date(byAdding: .day, value: -7, to: Date()) ?? Date()
            filteredAttempts = attempts.filter {
                $0.result.isSuccessful && $0.timestamp >= sevenDaysAgo
            }
        }

        // Get attempted problems
        let attemptedProblemIds = filteredAttempts.map { $0.problemId }
        let attemptedProblems = problems.filter { attemptedProblemIds.contains($0.id) }

        // Group by difficulty system and grade
        var gradeCounts: [String: GradeCount] = [:]

        for problem in attemptedProblems {
            let successfulAttemptsForProblem = filteredAttempts.filter {
                $0.problemId == problem.id
            }
            let count = successfulAttemptsForProblem.count

            let key = "\(problem.difficulty.system.rawValue)-\(problem.difficulty.grade)"

            if let existing = gradeCounts[key] {
                gradeCounts[key] = GradeCount(
                    grade: existing.grade,
                    count: existing.count + count,
                    gradeNumeric: existing.gradeNumeric,
                    difficultySystem: existing.difficultySystem
                )
            } else {
                gradeCounts[key] = GradeCount(
                    grade: problem.difficulty.grade,
                    count: count,
                    gradeNumeric: problem.difficulty.numericValue,
                    difficultySystem: problem.difficulty.system
                )
            }
        }

        return Array(gradeCounts.values)
    }
}

struct GradeCount {
    let grade: String
    let count: Int
    let gradeNumeric: Int
    let difficultySystem: DifficultySystem
}

struct BarChartView: View {
    let data: [GradeCount]
    @EnvironmentObject var themeManager: ThemeManager

    private var sortedData: [GradeCount] {
        data.sorted { $0.gradeNumeric < $1.gradeNumeric }
    }

    private var maxCount: Int {
        data.map { $0.count }.max() ?? 1
    }

    var body: some View {
        GeometryReader { geometry in
            let chartWidth = geometry.size.width - 40
            let chartHeight = geometry.size.height - 40
            let barWidth = chartWidth / CGFloat(max(sortedData.count, 1)) * 0.8
            let spacing = chartWidth / CGFloat(max(sortedData.count, 1)) * 0.2

            if sortedData.isEmpty {
                Rectangle()
                    .fill(.clear)
                    .overlay(
                        Text("No data")
                            .foregroundColor(.secondary)
                    )
            } else {
                VStack(alignment: .leading) {
                // Chart area
                    HStack(alignment: .bottom, spacing: spacing / CGFloat(sortedData.count)) {
                        ForEach(Array(sortedData.enumerated()), id: \.offset) { index, gradeCount in
                            VStack(spacing: 4) {
                                // Bar
                                RoundedRectangle(cornerRadius: 4)
                                    .fill(themeManager.accentColor)
                                    .frame(
                                        width: barWidth,
                                        height: CGFloat(gradeCount.count) / CGFloat(maxCount)
                                            * chartHeight * 0.8
                                    )
                                    .overlay(
                                        Text("\(gradeCount.count)")
                                            .font(.caption2)
                                            .fontWeight(.medium)
                                            .foregroundColor(themeManager.contrastingTextColor)
                                            .opacity(gradeCount.count > 0 ? 1 : 0)
                                    )

                                // Grade label
                                Text(gradeCount.grade)
                                    .font(.caption2)
                                    .foregroundColor(.secondary)
                                    .lineLimit(1)
                            }
                        }
                    }
                    .frame(height: chartHeight)
                }
                .frame(maxWidth: .infinity, alignment: .center)
            }
        }
    }
}

struct FavoriteGymSection: View {
    @EnvironmentObject var dataManager: ClimbingDataManager

    private var favoriteGymInfo: (gym: Gym, sessionCount: Int)? {
        let gymSessionCounts = Dictionary(grouping: dataManager.sessions, by: { $0.gymId })
            .mapValues { $0.count }

        guard let mostUsedGymId = gymSessionCounts.max(by: { $0.value < $1.value })?.key,
            let gym = dataManager.gym(withId: mostUsedGymId)
        else {
            return nil
        }

        return (gym, gymSessionCounts[mostUsedGymId] ?? 0)
    }

    var body: some View {
        VStack(alignment: .leading, spacing: 16) {
            HStack {
                Image(systemName: "location.fill")
                    .font(.title2)
                    .foregroundColor(.purple)

                Text("Favorite Gym")
                    .font(.title2)
                    .fontWeight(.bold)

                Spacer()
            }

            if let info = favoriteGymInfo {
                VStack(alignment: .leading, spacing: 12) {
                    Text(info.gym.name)
                        .font(.title3)
                        .fontWeight(.semibold)
                        .foregroundColor(.primary)

                    HStack {
                        Image(systemName: "calendar")
                            .font(.subheadline)
                            .foregroundColor(.purple)

                        Text("\(info.sessionCount) sessions")
                            .font(.subheadline)
                            .foregroundColor(.secondary)
                    }

                    Spacer()
                }
            } else {
                VStack(alignment: .leading, spacing: 8) {
                    Text("No sessions yet")
                        .font(.subheadline)
                        .foregroundColor(.secondary)

                    Text("Start climbing to see your favorite gym!")
                        .font(.caption)
                        .foregroundColor(.secondary)

                    Spacer()
                }
            }
        }
        .frame(maxWidth: .infinity, minHeight: 120, alignment: .topLeading)
        .padding()
        .background(
            RoundedRectangle(cornerRadius: 16)
                .fill(.regularMaterial)
        )
    }
}

struct RecentActivitySection: View {
    @EnvironmentObject var dataManager: ClimbingDataManager
    @EnvironmentObject var themeManager: ThemeManager

    private var recentSessionsCount: Int {
        dataManager.sessions.count
    }

    private var totalAttempts: Int {
        dataManager.attempts.count
    }

    var body: some View {
        VStack(alignment: .leading, spacing: 16) {
            HStack {
                Image(systemName: "clock.fill")
                    .font(.title2)
                    .foregroundColor(themeManager.accentColor)

                Text("Recent Activity")
                    .font(.title2)
                    .fontWeight(.bold)

                Spacer()
            }

            if recentSessionsCount > 0 {
                VStack(alignment: .leading, spacing: 12) {
                    HStack {
                        Image(systemName: "play.circle")
                            .font(.subheadline)
                            .foregroundColor(themeManager.accentColor)

                        Text("\(recentSessionsCount) sessions")
                            .font(.subheadline)
                            .foregroundColor(.secondary)
                    }

                    HStack {
                        Image(systemName: "hand.raised")
                            .font(.subheadline)
                            .foregroundColor(.green)

                        Text("\(totalAttempts) attempts")
                            .font(.subheadline)
                            .foregroundColor(.secondary)
                    }

                    Spacer()
                }
            } else {
                VStack(alignment: .leading, spacing: 8) {
                    Text("No recent activity")
                        .font(.subheadline)
                        .foregroundColor(.secondary)

                    Text("Start your first session!")
                        .font(.caption)
                        .foregroundColor(.secondary)

                    Spacer()
                }
            }
        }
        .frame(maxWidth: .infinity, minHeight: 120, alignment: .topLeading)
        .padding()
        .background(
            RoundedRectangle(cornerRadius: 16)
                .fill(.regularMaterial)
        )
    }
}

#Preview {
    AnalyticsView()
        .environmentObject(ClimbingDataManager.preview)
}
