import SwiftUI

struct TemporalDistributionChartView: View {
    let bins: [TemporalBin]
    let displayName: String
    let binningStrategy: BinningStrategy
    let onBinTap: (TemporalBin) -> Void
    let onResetZoom: () -> Void

    @State private var selectedBinIndex: Int? = nil

    private var maxCount: Int {
        bins.map { max($0.added, $0.disappeared, $0.unchanged) }.max() ?? 1
    }

    private var dateRangeLabel: String {
        guard !bins.isEmpty else { return "–" }
        let start = bins.first?.date ?? Date()
        let end = bins.last?.dateRange.end ?? Date()
        return "\(start.formatted(.dateTime.month().day())) – \(end.formatted(.dateTime.month().day()))"
    }

    private var durationLabel: String {
        guard !bins.isEmpty, let start = bins.first?.date, let end = bins.last?.dateRange.end else { return "–" }
        let days = Int(end.timeIntervalSince(start) / 86400)
        return "\(days)d"
    }

    var body: some View {
        VStack(spacing: 12) {
            headerSection
            chartSection
            if let selectedIndex = selectedBinIndex {
                selectedBinDetails(bins[selectedIndex], strategy: binningStrategy)
            }
        }
        .padding(16)
    }

    private var headerSection: some View {
        VStack(alignment: .leading, spacing: 8) {
            HStack {
                Text("Temporal Distribution")
                    .font(.headline.weight(.semibold))
                    .foregroundStyle(.primary)

                Spacer()

                Text(binningStrategy.rawValue)
                    .font(.caption)
                    .foregroundStyle(.secondary)
                    .padding(.horizontal, 8)
                    .padding(.vertical, 4)
                    .background(Color(.systemBackground).opacity(0.5), in: Capsule())
            }

            HStack(spacing: 12) {
                HStack(spacing: 4) {
                    Circle()
                        .fill(Color.healthyGreen.opacity(0.7))
                        .frame(width: 8, height: 8)
                    Text("Added")
                        .font(.caption)
                        .foregroundStyle(.secondary)
                }

                HStack(spacing: 4) {
                    Circle()
                        .fill(Color.criticalRed.opacity(0.7))
                        .frame(width: 8, height: 8)
                    Text("Disappeared")
                        .font(.caption)
                        .foregroundStyle(.secondary)
                }

                HStack(spacing: 4) {
                    Circle()
                        .fill(Color.neutralGray.opacity(0.5))
                        .frame(width: 8, height: 8)
                    Text("Unchanged")
                        .font(.caption)
                        .foregroundStyle(.secondary)
                }

                Spacer()
            }
            .padding(8)
            .background(Color(.systemBackground).opacity(0.5), in: RoundedRectangle(cornerRadius: 8))
        }
    }

    private var chartSection: some View {
        VStack(spacing: 8) {
            HStack(spacing: 12) {
                VStack(alignment: .leading, spacing: 2) {
                    Text("Range").font(.caption).foregroundStyle(.secondary)
                    Text(dateRangeLabel).font(.caption).monospacedDigit()
                }
                Spacer()
                VStack(alignment: .trailing, spacing: 2) {
                    Text("Duration").font(.caption).foregroundStyle(.secondary)
                    Text(durationLabel).font(.caption).monospacedDigit()
                }
            }
            .padding(8)
            .background(Color(.systemBackground).opacity(0.3), in: RoundedRectangle(cornerRadius: 6))

            ZStack(alignment: .topLeading) {
                Color(.systemBackground)
                    .opacity(0.3)
                    .cornerRadius(8)

                if bins.isEmpty {
                    VStack {
                        Text("No data for selected period")
                            .font(.subheadline)
                            .foregroundStyle(.secondary)
                    }
                    .frame(maxWidth: .infinity, maxHeight: .infinity)
                } else {
                    ScrollView(.horizontal, showsIndicators: true) {
                        VStack(alignment: .leading, spacing: 4) {
                            HStack(alignment: .bottom, spacing: 1) {
                                ForEach(Array(bins.enumerated()), id: \.offset) { index, bin in
                                    barStack(for: bin, maxValue: maxCount)
                                        .frame(minWidth: 24, maxWidth: 24)
                                        .frame(height: 100)
                                        .contentShape(Rectangle())
                                        .onTapGesture {
                                            selectedBinIndex = (selectedBinIndex == index) ? nil : index
                                            onBinTap(bin)
                                        }
                                        .background(
                                            selectedBinIndex == index
                                                ? Color.accentColor.opacity(0.1)
                                                : Color.clear,
                                            in: RoundedRectangle(cornerRadius: 2)
                                        )
                                }
                            }
                            .padding(.horizontal, 12)
                            .padding(.top, 12)
                            .padding(.bottom, 4)

                            HStack(spacing: 0) {
                                if !bins.isEmpty {
                                    VStack(alignment: .leading, spacing: 2) {
                                        Text(binningStrategy.label(for: bins.first!.date))
                                            .font(.caption2)
                                            .foregroundStyle(.secondary)
                                    }
                                    .frame(minWidth: 24)
                                    .padding(.horizontal, 12)

                                    Spacer(minLength: 0)

                                    if bins.count > 1 {
                                        VStack(alignment: .trailing, spacing: 2) {
                                            Text(binningStrategy.label(for: bins.last!.date))
                                                .font(.caption2)
                                                .foregroundStyle(.secondary)
                                        }
                                        .frame(minWidth: 24)
                                        .padding(.horizontal, 12)
                                    }
                                }
                            }
                            .padding(.bottom, 8)
                        }
                    }
                }
            }
            .frame(height: 160)
        }
    }

    private func barStack(for bin: TemporalBin, maxValue: Int) -> some View {
        let guardMaxValue = max(1, maxValue)
        let addedHeight = CGFloat(bin.added) / CGFloat(guardMaxValue) * 100
        let disappearedHeight = CGFloat(bin.disappeared) / CGFloat(guardMaxValue) * 100
        let unchangedHeight = CGFloat(bin.unchanged) / CGFloat(guardMaxValue) * 100

        return VStack(alignment: .center, spacing: 0) {
            if addedHeight > 0 {
                RoundedRectangle(cornerRadius: 1)
                    .fill(Color.healthyGreen.opacity(0.8))
                    .frame(height: addedHeight)
            }

            if unchangedHeight > 0 {
                RoundedRectangle(cornerRadius: 1)
                    .fill(Color.neutralGray.opacity(0.5))
                    .frame(height: unchangedHeight)
            }

            if disappearedHeight > 0 {
                RoundedRectangle(cornerRadius: 1)
                    .fill(Color.criticalRed.opacity(0.8))
                    .frame(height: disappearedHeight)
            }

            Spacer()
        }
    }

    @ViewBuilder
    private func selectedBinDetails(_ bin: TemporalBin, strategy: BinningStrategy) -> some View {
        VStack(alignment: .leading, spacing: 8) {
            HStack {
                VStack(alignment: .leading, spacing: 2) {
                    Text("Period")
                        .font(.caption)
                        .foregroundStyle(.secondary)

                    Text("\(bin.dateRange.start.formatted(.dateTime.year().month().day())) – \(bin.dateRange.end.formatted(.dateTime.year().month().day()))")
                        .font(.subheadline.weight(.semibold))
                }

                Spacer()

                VStack(alignment: .trailing, spacing: 2) {
                    Text("Total")
                        .font(.caption)
                        .foregroundStyle(.secondary)
                    Text("\(bin.total)")
                        .font(.subheadline.weight(.semibold))
                        .monospacedDigit()
                }
            }
            .padding(12)
            .background(Color(.systemBackground).opacity(0.5), in: RoundedRectangle(cornerRadius: 8))

            Divider()

            HStack {
                detailMetric("Added", bin.added, Color.healthyGreen)
                Spacer()
                detailMetric("Unchanged", bin.unchanged, Color.neutralGray)
                Spacer()
                detailMetric("Disappeared", bin.disappeared, Color.criticalRed)
            }
        }
        .padding(12)
        .background(Color(.systemBackground).opacity(0.5), in: RoundedRectangle(cornerRadius: 8))
    }

    private func detailMetric(_ label: String, _ value: Int, _ color: Color) -> some View {
        VStack(alignment: .center, spacing: 4) {
            Text(label)
                .font(.caption2)
                .foregroundStyle(.secondary)
            Text("\(value)")
                .font(.headline)
                .foregroundStyle(color)
                .monospacedDigit()
        }
    }
}

#Preview {
    let mockBins = (0..<12).map { monthOffset in
        let date = Calendar.current.date(byAdding: .month, value: monthOffset, to: Date.now.addingTimeInterval(-365 * 86400)) ?? .now
        let nextDate = Calendar.current.date(byAdding: .month, value: 1, to: date) ?? date
        return TemporalBin(
            date: date,
            dateRange: (date, nextDate),
            added: Int.random(in: 0..<50),
            disappeared: Int.random(in: 0..<30),
            unchanged: Int.random(in: 500..<2000)
        )
    }

    TemporalDistributionChartView(
        bins: mockBins,
        displayName: "Sleep",
        binningStrategy: .month,
        onBinTap: { _ in },
        onResetZoom: { }
    )
        .frame(height: 400)
}
