//
// TrendsSection.swift
// Workouts
//
// Copyright 2026 Rouslan Zenetl. All Rights Reserved.
//

import SwiftUI
import Charts

/// Aggregate trends over time: one chart, a metric picker (workouts, volume, active
/// time, energy), and the standard 7D/30D/90D/1Y/All range picker. Counts render as
/// bars (discrete events); the other metrics as the smooth line + points pattern.
struct TrendsSection: View {
    let workouts: [WorkoutFacts]

    @AppStorage("weightUnit") private var weightUnit: WeightUnit = .lb
    @State private var range: TrendRange = .month
    @State private var metric: Metric = .workouts

    enum Metric: String, CaseIterable, Identifiable {
        case workouts = "Workouts"
        case volume = "Volume"
        case time = "Time"
        case energy = "Energy"

        var id: String { rawValue }

        var color: Color {
            switch self {
            case .workouts: .blue
            case .volume: .purple
            case .time: .green
            case .energy: .orange
            }
        }
    }

    var body: some View {
        VStack(alignment: .leading, spacing: 12) {
            Text("Trends")
                .font(.headline)

            Picker("Metric", selection: $metric) {
                ForEach(Metric.allCases) { metric in
                    Text(metric.rawValue).tag(metric)
                }
            }
            .pickerStyle(.segmented)

            Picker("Range", selection: $range) {
                ForEach(TrendRange.allCases) { range in
                    Text(range.rawValue).tag(range)
                }
            }
            .pickerStyle(.segmented)

            chart
        }
        .progressCard()
    }

    @ViewBuilder
    private var chart: some View {
        let points = ProgressPlanner.trendPoints(workouts: workouts, range: range)
        if points.isEmpty || points.allSatisfy({ $0.workouts == 0 }) {
            ContentUnavailableView(
                "No Data",
                systemImage: "chart.xyaxis.line",
                description: Text(workouts.contains(where: \.completed)
                    ? "No workouts in this time range. Try a wider range."
                    : "Complete workouts and your trends build up here."))
                .frame(height: 220)
        } else {
            Chart(points) { point in
                if metric == .workouts {
                    BarMark(
                        x: .value("Date", point.date, unit: range.bucket),
                        y: .value(metric.rawValue, value(of: point))
                    )
                    .foregroundStyle(metric.color.gradient)
                    .cornerRadius(3)
                } else {
                    LineMark(
                        x: .value("Date", point.date, unit: range.bucket),
                        y: .value(metric.rawValue, value(of: point))
                    )
                    .interpolationMethod(.catmullRom)
                    .foregroundStyle(metric.color.gradient)

                    PointMark(
                        x: .value("Date", point.date, unit: range.bucket),
                        y: .value(metric.rawValue, value(of: point))
                    )
                    .symbolSize(30)
                    .foregroundStyle(metric.color)
                }
            }
            .chartYAxisLabel(unitLabel)
            .chartXAxis {
                AxisMarks(values: .automatic) { _ in
                    AxisGridLine()
                    AxisValueLabel(format: axisDateFormat)
                }
            }
            .frame(height: 220)
        }
    }

    private func value(of point: TrendPoint) -> Double {
        switch metric {
        case .workouts: Double(point.workouts)
        case .volume: point.volume
        case .time: point.activeMinutes
        case .energy: point.energyKcal
        }
    }

    private var unitLabel: String {
        switch metric {
        case .workouts: ""
        case .volume: weightUnit.abbreviation
        case .time: "min"
        case .energy: "kcal"
        }
    }

    private var axisDateFormat: Date.FormatStyle {
        switch range.bucket {
        case .month: .dateTime.month(.abbreviated)
        default: .dateTime.month().day()
        }
    }
}
