import SwiftUI
import SwiftData
import os

struct MetricsContent: View {
    private let logger = Logger(subsystem: "com.prakashjoshipax.VoiceInk", category: "MetricsContent")
    let modelContext: ModelContext

    @State private var totalCount: Int = 0
    @State private var totalWords: Int = 0
    @State private var totalDuration: TimeInterval = 0
    @State private var isLoadingMetrics: Bool = true
    @State private var metricsTask: Task<Void, Never>?
    @State private var isModelStatsPanelPresented = false

    var body: some View {
        Group {
            if totalCount == 0 && !isLoadingMetrics {
                emptyStateView
            } else if isLoadingMetrics {
                ProgressView("Statistieken laden…")
                    .frame(maxWidth: .infinity, maxHeight: .infinity)
            } else {
                GeometryReader { geometry in
                    ScrollView {
                        VStack(spacing: ProatSpacing.l) {
                            heroSection
                            metricsSection
                            HStack(alignment: .top, spacing: ProatSpacing.m) {
                                HelpAndResourcesSection()
                            }

                            Spacer(minLength: ProatSpacing.l)

                            HStack {
                                Spacer()
                                footerActionsView
                            }
                        }
                        .frame(minHeight: geometry.size.height - 56)
                        .padding(.vertical, ProatSpacing.xl)
                        .padding(.horizontal, ProatSpacing.xl)
                    }
                    .background(Color.proatBgBase)
                }
            }
        }
        .task {
            await loadMetricsEfficiently()
        }
        .onReceive(NotificationCenter.default.publisher(for: .sessionMetricsDidChange)) { _ in
            metricsTask?.cancel()
            metricsTask = Task {
                await loadMetricsEfficiently()
            }
        }
        .onDisappear {
            metricsTask?.cancel()
        }
        .overlay {
            Color.black.opacity(isModelStatsPanelPresented ? 0.1 : 0)
                .ignoresSafeArea()
                .allowsHitTesting(isModelStatsPanelPresented)
                .onTapGesture {
                    withAnimation(.smooth(duration: 0.3)) { isModelStatsPanelPresented = false }
                }
                .animation(.smooth(duration: 0.3), value: isModelStatsPanelPresented)
        }
        .overlay(alignment: .trailing) {
            if isModelStatsPanelPresented {
                ModelPerformancePanel {
                    withAnimation(.smooth(duration: 0.3)) { isModelStatsPanelPresented = false }
                }
                .frame(width: 400)
                .frame(maxHeight: .infinity)
                .background(Color.proatBgRaised)
                .overlay(alignment: .leading) {
                    Rectangle().fill(Color.proatBorder).frame(width: 1)
                }
                .proatShadowFloat()
                .ignoresSafeArea()
                .transition(.move(edge: .trailing))
            }
        }
        .animation(.smooth(duration: 0.3), value: isModelStatsPanelPresented)
    }
    
    private func loadMetricsEfficiently() async {
        await MainActor.run {
            self.isLoadingMetrics = true
        }

        let modelContainer = modelContext.container

        let backgroundContext = ModelContext(modelContainer)

        do {
            guard !Task.isCancelled else {
                await MainActor.run {
                    self.isLoadingMetrics = false
                }
                return
            }

            let count = try backgroundContext.fetchCount(FetchDescriptor<SessionMetric>())

            guard !Task.isCancelled else {
                await MainActor.run {
                    self.isLoadingMetrics = false
                }
                return
            }

            var descriptor = FetchDescriptor<SessionMetric>()
            descriptor.propertiesToFetch = [\.wordCount, \.audioDuration]

            var words = 0
            var duration: TimeInterval = 0

            try backgroundContext.enumerate(descriptor) { metric in
                words += metric.wordCount
                duration += metric.audioDuration
            }

            guard !Task.isCancelled else {
                await MainActor.run { self.isLoadingMetrics = false }
                return
            }

            await MainActor.run {
                self.totalCount = count
                self.totalWords = words
                self.totalDuration = duration
                // Stay in loading state if migration is still running and no data yet —
                // sessionMetricsDidChange will trigger a reload when it finishes.
                if count > 0 || !SessionMetricMigrationService.shared.isRunning {
                    self.isLoadingMetrics = false
                }
            }
        } catch {
            logger.error("Error loading metrics: \(error.localizedDescription, privacy: .public)")
            await MainActor.run { self.isLoadingMetrics = false }
        }
    }

    private var emptyStateView: some View {
        VStack(spacing: ProatSpacing.m) {
            ProatBrandMark(size: 40, showCaption: true, opacity: 0.55)
            Image(systemName: "waveform")
                .font(.system(size: 56, weight: .semibold))
                .foregroundColor(.proatTeal)
            Text("Nog geen opnamesessies")
                .font(ProatFont.titel)
                .foregroundColor(.proatText1)
            Text("Start je eerste opname om waardevolle inzichten te ontgrendelen.")
                .font(ProatFont.body)
                .foregroundColor(.proatText2)
        }
        .frame(maxWidth: .infinity, maxHeight: .infinity)
        .background(Color.proatBgBase)
    }
    
    // MARK: - Sections
    
    private var heroSection: some View {
        VStack(spacing: 10) {
            HStack {
                Spacer(minLength: 0)
                
                (Text("Je hebt ")
                    .fontWeight(.bold)
                    .foregroundColor(.white.opacity(0.85))
                 +
                 Text(formattedTimeSaved)
                    .fontWeight(.black)
                    .font(.system(size: 36, design: .rounded))
                    .foregroundStyle(.white)
                 +
                 Text(" bespaard met Proat")
                    .fontWeight(.bold)
                    .foregroundColor(.white.opacity(0.85))
                )
                .font(.system(size: 30))
                .multilineTextAlignment(.center)
                
                Spacer(minLength: 0)
            }
            .lineLimit(1)
            .minimumScaleFactor(0.5)
            
            Text(heroSubtitle)
                .font(.system(size: 15, weight: .semibold))
                .foregroundColor(.white)
                .shadow(color: .black.opacity(0.22), radius: 2, y: 1)
                .multilineTextAlignment(.center)
                .frame(maxWidth: .infinity)
            
        }
        .padding(ProatSpacing.xl)
        .frame(maxWidth: .infinity)
        .background(
            RoundedRectangle(cornerRadius: ProatRadius.kaart, style: .continuous)
                .fill(LinearGradient.proatTeal)
        )
        .overlay(
            RoundedRectangle(cornerRadius: ProatRadius.kaart, style: .continuous)
                .strokeBorder(Color.white.opacity(0.12), lineWidth: 1)
        )
        .clipShape(RoundedRectangle(cornerRadius: ProatRadius.kaart, style: .continuous))
        .proatShadowKaart()
    }
    
    private var metricsSection: some View {
        LazyVGrid(columns: [GridItem(.adaptive(minimum: 240), spacing: ProatSpacing.m)], spacing: ProatSpacing.m) {
            MetricCard(
                icon: "mic.fill",
                title: "Opgenomen sessies",
                value: "\(totalCount)",
                detail: "Proat-sessies voltooid",
                color: .purple
            )

            MetricCard(
                icon: "text.alignleft",
                title: "Gedicteerde woorden",
                value: Formatters.formattedNumber(totalWords),
                detail: "woorden gegenereerd",
                color: Color.proatTeal
            )
            
            MetricCard(
                icon: "speedometer",
                title: "Woorden per minuut",
                value: averageWordsPerMinute > 0
                    ? String(format: "%.1f", averageWordsPerMinute)
                    : "–",
                detail: "Proat vs. met de hand typen",
                color: .yellow
            )
            
            MetricCard(
                icon: "keyboard.fill",
                title: "Bespaarde toetsaanslagen",
                value: Formatters.formattedNumber(totalKeystrokesSaved),
                detail: "minder toetsaanslagen",
                color: .orange
            )
        }
    }

    private var footerActionsView: some View {
        HStack(spacing: ProatSpacing.s) {
            Button(action: {
                withAnimation(.smooth(duration: 0.3)) { isModelStatsPanelPresented = true }
            }) {
                HStack(spacing: ProatSpacing.xs) {
                    Image(systemName: "gauge")
                    Text("Modelprestaties")
                }
                .font(ProatFont.klein)
                .foregroundColor(.proatText1)
                .padding(.horizontal, ProatSpacing.s)
                .padding(.vertical, ProatSpacing.xs)
                .background(
                    Capsule()
                        .fill(Color.proatBgRaised)
                        .overlay(Capsule().stroke(Color.proatBorder, lineWidth: 1))
                )
            }
            .buttonStyle(.plain)
            .help("Bekijk prestaties van transcriptie- en verfijningsmodellen")
            CopySystemInfoButton()
        }
    }
    
    private var formattedTimeSaved: String {
        let formatted = Formatters.formattedDuration(timeSaved, style: .full, fallback: "Tijdsbesparing komt binnenkort")
        return formatted
    }
    
    private var heroSubtitle: String {
        guard totalCount > 0 else {
            return "Je Proat-reis begint met je eerste opname."
        }

        let wordsText = Formatters.formattedNumber(totalWords)
        let sessionText = totalCount == 1 ? "sessie" : "sessies"

        return "\(wordsText) woorden gedicteerd in \(totalCount) \(sessionText)."
    }
    
    private var heroGradient: LinearGradient {
        LinearGradient.proatTeal
    }
    
    // MARK: - Computed Metrics

    private var estimatedTypingTime: TimeInterval {
        let averageTypingSpeed: Double = 35 // words per minute
        let estimatedTypingTimeInMinutes = Double(totalWords) / averageTypingSpeed
        return estimatedTypingTimeInMinutes * 60
    }

    private var timeSaved: TimeInterval {
        max(estimatedTypingTime - totalDuration, 0)
    }

    private var averageWordsPerMinute: Double {
        guard totalDuration > 0 else { return 0 }
        return Double(totalWords) / (totalDuration / 60.0)
    }

    private var totalKeystrokesSaved: Int {
        Int(Double(totalWords) * 5.0)
    }
    
}

private enum Formatters {
    static let numberFormatter: NumberFormatter = {
        let formatter = NumberFormatter()
        formatter.numberStyle = .decimal
        return formatter
    }()
    
    static let durationFormatter: DateComponentsFormatter = {
        let formatter = DateComponentsFormatter()
        formatter.maximumUnitCount = 2
        var calendar = Calendar.current
        calendar.locale = Locale(identifier: "nl_NL")
        formatter.calendar = calendar
        return formatter
    }()
    
    static func formattedNumber(_ value: Int) -> String {
        return numberFormatter.string(from: NSNumber(value: value)) ?? "\(value)"
    }
    
    static func formattedDuration(_ interval: TimeInterval, style: DateComponentsFormatter.UnitsStyle, fallback: String = "–") -> String {
        guard interval > 0 else { return fallback }
        durationFormatter.unitsStyle = style
        durationFormatter.allowedUnits = interval >= 3600 ? [.hour, .minute] : [.minute, .second]
        return durationFormatter.string(from: interval) ?? fallback
    }
}

private struct CopySystemInfoButton: View {
    @State private var isCopied: Bool = false

    var body: some View {
        Button(action: {
            copySystemInfo()
        }) {
            HStack(spacing: 8) {
                Image(systemName: isCopied ? "checkmark" : "doc.on.doc")
                    .rotationEffect(.degrees(isCopied ? 360 : 0))
                    .animation(.spring(response: 0.3, dampingFraction: 0.7), value: isCopied)

                Text(isCopied ? "Gekopieerd!" : "Systeeminfo kopiëren")
                    .animation(.spring(response: 0.3, dampingFraction: 0.7), value: isCopied)
            }
            .font(ProatFont.klein)
            .foregroundColor(isCopied ? .proatTeal : .proatText1)
            .padding(.horizontal, ProatSpacing.s)
            .padding(.vertical, ProatSpacing.xs)
            .background(
                Capsule()
                    .fill(Color.proatBgRaised)
                    .overlay(Capsule().stroke(Color.proatBorder, lineWidth: 1))
            )
        }
        .buttonStyle(.plain)
        .scaleEffect(isCopied ? 1.1 : 1.0)
        .animation(.spring(response: 0.3, dampingFraction: 0.7), value: isCopied)
    }

    private func copySystemInfo() {
        SystemInfoService.shared.copySystemInfoToClipboard()

        withAnimation(.spring(response: 0.3, dampingFraction: 0.7)) {
            isCopied = true
        }

        DispatchQueue.main.asyncAfter(deadline: .now() + 1.5) {
            withAnimation(.spring(response: 0.3, dampingFraction: 0.7)) {
                isCopied = false
            }
        }
    }
}
