// LoopFollow
// AggregatedStatsView.swift

import SwiftUI
import UIKit

struct AggregatedStatsView: View {
    @ObservedObject var viewModel: AggregatedStatsViewModel
    @Environment(\.dismiss) var dismiss
    var onDismiss: (() -> Void)?
    @State private var showGMI: Bool
    @State private var showStdDev: Bool
    @State private var startDate: Date
    @State private var endDate: Date
    @State private var isLoadingData = false
    @State private var showLoadingMessage = false
    @State private var loadingError = false
    @State private var loadingTimer: Timer?
    @State private var timeoutTimer: Timer?

    init(viewModel: AggregatedStatsViewModel, onDismiss: (() -> Void)? = nil) {
        self.viewModel = viewModel
        self.onDismiss = onDismiss
        _showGMI = State(initialValue: UnitSettingsStore.shared.glycemicMetricMode == .gmi)
        _showStdDev = State(initialValue: UnitSettingsStore.shared.variabilityMetricMode == .stdDeviation)

        let range = StatsDateRange.lastComplete(days: 7)
        _startDate = State(initialValue: range.start)
        _endDate = State(initialValue: range.end)
    }

    var body: some View {
        ScrollView {
            VStack(spacing: 20) {
                VStack(spacing: 12) {
                    Text("Statistics")
                        .font(.largeTitle)
                        .fontWeight(.bold)

                    DateRangePicker(
                        startDate: $startDate,
                        endDate: $endDate,
                        availability: viewModel.dataAvailability,
                        onDateChange: {
                            loadingError = false
                            isLoadingData = true
                            viewModel.updateDateRange(start: startDate, end: endDate) {
                                isLoadingData = false
                            }
                        }
                    )
                    .padding(.horizontal)
                }
                .padding(.top)

                if loadingError {
                    VStack(spacing: 8) {
                        Text("#WeAreNotWaitingAnymore")
                            .font(.subheadline)
                            .fontWeight(.medium)
                            .foregroundColor(.orange)
                        Text("...because the data could not be loaded")
                            .font(.caption)
                            .foregroundColor(.secondary)
                    }
                    .padding()
                } else if isLoadingData {
                    VStack(spacing: 12) {
                        ProgressView("Loading data...")
                        if showLoadingMessage {
                            Text("#WeAreWaitingForData")
                                .font(.caption)
                                .foregroundColor(.secondary)
                        }
                    }
                    .padding()
                }

                StatsGridView(
                    simpleStats: viewModel.simpleStats,
                    showGMI: $showGMI,
                    showStdDev: $showStdDev
                )
                .padding(.horizontal)
                .opacity(isLoadingData ? 0.4 : 1.0)
                .disabled(isLoadingData)

                AGPView(viewModel: viewModel.agpStats)
                    .padding(.horizontal)
                    .opacity(isLoadingData ? 0.4 : 1.0)

                TIRView(viewModel: viewModel.tirStats)
                    .padding(.horizontal)
                    .opacity(isLoadingData ? 0.4 : 1.0)

                GRIView(viewModel: viewModel.griStats)
                    .padding(.horizontal)
                    .opacity(isLoadingData ? 0.4 : 1.0)
            }
            .padding(.bottom)
            .frame(maxWidth: .infinity)
        }
        .navigationBarTitleDisplayMode(.inline)
        .toolbar {
            if let onDismiss {
                ToolbarItem(placement: .navigationBarLeading) {
                    Button("Done", action: onDismiss)
                }
            }
            ToolbarItem(placement: .navigationBarTrailing) {
                Button("Refresh") {
                    loadingError = false
                    isLoadingData = true
                    viewModel.updateDateRange(start: startDate, end: endDate) {
                        isLoadingData = false
                    }
                }
            }
        }
        .onAppear {
            loadingError = false
            isLoadingData = true
            viewModel.updateDateRange(start: startDate, end: endDate) {
                isLoadingData = false
            }
        }
        .onChange(of: isLoadingData) { newValue in
            if newValue {
                showLoadingMessage = false
                loadingError = false

                // Show "still waiting" message after 3 seconds
                loadingTimer = Timer.scheduledTimer(withTimeInterval: 3.0, repeats: false) { _ in
                    showLoadingMessage = true
                }

                // Timeout after 30 seconds
                timeoutTimer = Timer.scheduledTimer(withTimeInterval: 30.0, repeats: false) { _ in
                    if self.isLoadingData {
                        self.isLoadingData = false
                        self.loadingError = true
                        self.viewModel.clearAllStats()
                    }
                }
            } else {
                loadingTimer?.invalidate()
                loadingTimer = nil
                timeoutTimer?.invalidate()
                timeoutTimer = nil
                showLoadingMessage = false
            }
        }
        .onDisappear {
            loadingTimer?.invalidate()
            loadingTimer = nil
            timeoutTimer?.invalidate()
            timeoutTimer = nil
        }
        .onChange(of: showGMI) { newValue in
            UnitSettingsStore.shared.glycemicMetricMode = newValue ? .gmi : .ehba1c
        }
        .onChange(of: showStdDev) { newValue in
            UnitSettingsStore.shared.variabilityMetricMode = newValue ? .stdDeviation : .cv
        }
        .onReceive(Storage.shared.showGMI.$value) { newValue in
            showGMI = newValue
        }
        .onReceive(Storage.shared.showStdDev.$value) { newValue in
            showStdDev = newValue
        }
        .onReceive(Storage.shared.units.$value) { _ in
            refreshVisibleStats()
        }
        .onReceive(Storage.shared.useIFCC.$value) { _ in
            refreshVisibleStats()
        }
        .onReceive(Storage.shared.timeInRangeModeRaw.$value) { _ in
            viewModel.tirStats.calculateTIR()
        }
    }

    private func refreshVisibleStats() {
        guard !isLoadingData else { return }
        viewModel.calculateStats()
    }
}

struct AggregatedStatsContentView: View {
    @StateObject private var viewModel: AggregatedStatsViewModel
    private let onDismiss: (() -> Void)?

    init(mainViewController: MainViewController?, onDismiss: (() -> Void)? = nil) {
        _viewModel = StateObject(wrappedValue: AggregatedStatsViewModel(mainViewController: mainViewController))
        self.onDismiss = onDismiss
    }

    var body: some View {
        AggregatedStatsView(viewModel: viewModel, onDismiss: onDismiss)
            .preferredColorScheme(Storage.shared.appearanceMode.value.colorScheme)
    }
}

struct AggregatedStatsModalView: View {
    @Environment(\.dismiss) private var dismiss

    let mainViewController: MainViewController?

    var body: some View {
        NavigationView {
            AggregatedStatsContentView(
                mainViewController: mainViewController,
                onDismiss: { dismiss() }
            )
            .navigationBarTitleDisplayMode(.inline)
        }
        .preferredColorScheme(Storage.shared.appearanceMode.value.colorScheme)
    }
}

struct StatCard: View {
    let title: String
    let value: String
    let unit: String?
    let color: Color
    var isInteractive: Bool = false

    var body: some View {
        ZStack(alignment: .topTrailing) {
            VStack(alignment: .leading, spacing: 8) {
                Text(title)
                    .font(.caption)
                    .foregroundColor(.secondary)

                HStack(alignment: .firstTextBaseline, spacing: 4) {
                    Text(value)
                        .font(.title2)
                        .fontWeight(.semibold)
                        .foregroundColor(color)

                    if let unit = unit {
                        Text(unit)
                            .font(.caption)
                            .foregroundColor(.secondary)
                    }
                }
            }
            .frame(maxWidth: .infinity, alignment: .leading)
            .padding()

            if isInteractive {
                Image(systemName: "chevron.up.chevron.down")
                    .font(.caption2)
                    .foregroundColor(.secondary.opacity(0.5))
                    .padding(8)
            }
        }
        .background(Color(.systemGray6))
        .cornerRadius(12)
    }
}

struct InsulinTotalsCard: View {
    let totalNegativeBasal: Double?
    let totalPositiveBasal: Double?
    let programmedBasal: Double?
    let actualBasal: Double?
    let avgBolus: Double?
    let totalDailyDose: Double?

    var body: some View {
        VStack(alignment: .leading, spacing: 8) {
            Text("Insulin Totals")
                .font(.caption)
                .foregroundColor(.secondary)

            VStack(spacing: 10) {
                metricRow(title: "Programmed Basal", value: programmedBasal, color: .indigo)
                metricRow(title: "Total Negative Basal", value: totalNegativeBasal, color: .red)
                metricRow(title: "Total Positive Basal", value: totalPositiveBasal, color: .green)
                metricRow(title: "Actual Basal", value: actualBasal, color: .indigo)
                metricRow(title: "Avg Bolus", value: avgBolus, color: .purple)
                metricRow(title: "Total Daily Dose", value: totalDailyDose, color: .pink)
            }
        }
        .frame(maxWidth: .infinity, alignment: .leading)
        .padding()
        .background(Color(.systemGray6))
        .cornerRadius(12)
    }

    @ViewBuilder
    private func metricRow(title: String, value: Double?, color: Color) -> some View {
        HStack(alignment: .firstTextBaseline) {
            Text(title)
                .font(.subheadline)
                .foregroundColor(.secondary)

            Spacer()

            Text(formatBasal(value))
                .font(.headline)
                .fontWeight(.semibold)
                .foregroundColor(color)
                + Text(" U")
                .font(.caption)
                .foregroundColor(.secondary)
        }
    }

    private func formatBasal(_ value: Double?) -> String {
        guard let value = value else { return "---" }
        return String(format: "%.2f", value)
    }
}

struct StatsGridView: View {
    @ObservedObject var simpleStats: SimpleStatsViewModel
    @Binding var showGMI: Bool
    @Binding var showStdDev: Bool
    @State private var showInsulinBreakdown = false

    private var hasInsulinData: Bool {
        simpleStats.totalDailyDose != nil || simpleStats.avgBolus != nil || simpleStats.actualBasal != nil || simpleStats.programmedBasal != nil
    }

    private var hasCarbData: Bool {
        simpleStats.avgCarbs != nil
    }

    var body: some View {
        VStack(spacing: 16) {
            LazyVGrid(columns: [GridItem(.flexible()), GridItem(.flexible())], spacing: 16) {
                Button(action: {
                    showGMI.toggle()
                }) {
                    StatCard(
                        title: showGMI ? "GMI" : "Est. A1C",
                        value: showGMI ? formatGMI(simpleStats.avgGlucose) : formatEhbA1c(simpleStats.avgGlucose),
                        unit: UnitSettingsStore.shared.glycemicOutputUnit.rawValue,
                        color: .blue,
                        isInteractive: true
                    )
                }
                .buttonStyle(PlainButtonStyle())

                StatCard(
                    title: "Avg Glucose",
                    value: formatGlucose(simpleStats.avgGlucose),
                    unit: UnitSettingsStore.shared.glucoseUnit.rawValue,
                    color: Color(red: 0.20, green: 0.99, blue: 0.70)
                )

                Button(action: {
                    showStdDev.toggle()
                }) {
                    StatCard(
                        title: showStdDev ? "Std Deviation" : "CV",
                        value: showStdDev ? formatStdDev(simpleStats.stdDeviation) : formatCV(simpleStats.coefficientOfVariation),
                        unit: showStdDev ? UnitSettingsStore.shared.glucoseUnit.rawValue : "%",
                        color: .orange,
                        isInteractive: true
                    )
                }
                .buttonStyle(PlainButtonStyle())

                if hasCarbData {
                    StatCard(
                        title: "Avg Carbs",
                        value: formatCarbs(simpleStats.avgCarbs),
                        unit: "g/day",
                        color: .yellow
                    )
                }

                if hasInsulinData {
                    StatCard(
                        title: "Programmed Basal",
                        value: formatInsulin(simpleStats.programmedBasal),
                        unit: "U/day",
                        color: .indigo
                    )
                    .onTapGesture(count: 3) {
                        showInsulinBreakdown = true
                    }

                    StatCard(
                        title: "Avg Bolus",
                        value: formatInsulin(simpleStats.avgBolus),
                        unit: "U/day",
                        color: .purple
                    )
                    .onTapGesture(count: 3) {
                        showInsulinBreakdown = true
                    }

                    StatCard(
                        title: "Total Daily Dose",
                        value: formatInsulin(simpleStats.totalDailyDose),
                        unit: "U",
                        color: .pink
                    )
                    .onTapGesture(count: 3) {
                        showInsulinBreakdown = true
                    }
                }
            }

            if hasInsulinData && showInsulinBreakdown {
                InsulinTotalsCard(
                    totalNegativeBasal: simpleStats.totalNegativeBasal,
                    totalPositiveBasal: simpleStats.totalPositiveBasal,
                    programmedBasal: simpleStats.programmedBasal,
                    actualBasal: simpleStats.actualBasal,
                    avgBolus: simpleStats.avgBolus,
                    totalDailyDose: simpleStats.totalDailyDose
                )
            }
        }
    }

    private func formatGMI(_ avgGlucose: Double?) -> String {
        guard let value = GlycemicMetricCalculator.calculateGMI(avgGlucoseInDisplayUnits: avgGlucose) else { return "---" }
        if UnitSettingsStore.shared.glycemicOutputUnit == .mmolMol {
            return String(format: "%.0f", value)
        }
        return String(format: "%.1f", value)
    }

    private func formatEhbA1c(_ avgGlucose: Double?) -> String {
        guard let value = GlycemicMetricCalculator.calculateEhba1c(avgGlucoseInDisplayUnits: avgGlucose) else { return "---" }
        if UnitSettingsStore.shared.glycemicOutputUnit == .mmolMol {
            return String(format: "%.0f", value)
        }
        return String(format: "%.1f", value)
    }

    private func formatGlucose(_ value: Double?) -> String {
        guard let value = value else { return "---" }
        if UnitSettingsStore.shared.glucoseUnit == .mgdL {
            return String(format: "%.0f", value)
        } else {
            return String(format: "%.1f", value)
        }
    }

    private func formatStdDev(_ value: Double?) -> String {
        guard let value = value else { return "---" }
        if UnitSettingsStore.shared.glucoseUnit == .mgdL {
            return String(format: "%.0f", value)
        } else {
            return String(format: "%.1f", value)
        }
    }

    private func formatInsulin(_ value: Double?) -> String {
        guard let value = value else { return "---" }
        return String(format: "%.2f", value)
    }

    private func formatCarbs(_ value: Double?) -> String {
        guard let value = value else { return "---" }
        return String(format: "%.0f", value)
    }

    private func formatCV(_ value: Double?) -> String {
        guard let value = value else { return "---" }
        return String(format: "%.1f", value)
    }
}
