import SwiftUI
import Charts

struct YearOverYearChartView: View {
    @ObservedObject var viewModel: ChartsViewModel
    @State private var selectedMonthIdx: Int?

    private let monthAbbreviations = ["Jan", "Feb", "Mar", "Apr", "May", "Jun",
                                      "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"]
    private let lineColors: [Color] = [
        .appPrimary, .appSecondary, .orange, .purple, .pink, .teal
    ]

    private var allYears: [ChartsViewModel.YearSeries] { viewModel.yearOverYearData }

    private var selectedSeries: [ChartsViewModel.YearSeries] {
        allYears.filter { viewModel.yoySelectedYears.contains($0.year) }
            .sorted { $0.year < $1.year }
    }

    var body: some View {
        VStack(alignment: .leading, spacing: 16) {
            Text(String(localized: "chart_yoy_title"))
                .font(.headline)

            if allYears.isEmpty {
                Text(String(localized: "chart_yoy_empty"))
                    .font(.subheadline)
                    .foregroundColor(.secondary)
                    .frame(maxWidth: .infinity, alignment: .center)
                    .frame(height: 200)
            } else {
                yearSelector
                if !selectedSeries.isEmpty {
                    // KPIs arriba del todo (#147)
                    yearEndStatsRow
                    if selectedSeries.count == 2 {
                        comparisonStatsHeader
                    }
                    if hasEstimate {
                        Text(String(localized: "chart_yoy_estimated_note"))
                            .font(.caption2)
                            .foregroundColor(.secondary)
                    }
                    // Detalle debajo (#147)
                    chartBody
                    legend
                    if selectedSeries.count == 2 {
                        comparisonTable
                    }
                }
            }
        }
        .padding()
        .background(Color(.systemBackground))
        .cornerRadius(AppConstants.UI.cornerRadius)
        .shadow(color: .black.opacity(0.05), radius: 8, y: 2)
    }

    // MARK: - Year Selector

    private var yearSelector: some View {
        ScrollView(.horizontal, showsIndicators: false) {
            HStack(spacing: 8) {
                ForEach(allYears) { ys in
                    let idx = allYears.firstIndex(where: { $0.id == ys.id }) ?? 0
                    let color = lineColors[idx % lineColors.count]
                    let isSelected = viewModel.yoySelectedYears.contains(ys.year)
                    Button {
                        if isSelected {
                            viewModel.yoySelectedYears.remove(ys.year)
                        } else {
                            viewModel.yoySelectedYears.insert(ys.year)
                        }
                    } label: {
                        Text(String(ys.year))
                            .font(.caption.weight(.medium))
                            .padding(.horizontal, 12)
                            .padding(.vertical, 6)
                            .background(isSelected ? color.opacity(0.15) : Color.gray.opacity(0.1))
                            .foregroundColor(isSelected ? color : .secondary)
                            .overlay(
                                RoundedRectangle(cornerRadius: 16)
                                    .stroke(isSelected ? color : Color.clear, lineWidth: 1.5)
                            )
                            .cornerRadius(16)
                    }
                    .buttonStyle(.plain)
                }
            }
        }
    }

    // MARK: - Chart

    /// Two selected years × 12 months stays readable with permanent labels.
    private var showAllLabels: Bool { selectedSeries.count <= 2 }

    private func selectionRows(for month: Int) -> [(label: String, value: String, color: Color)] {
        selectedSeries.compactMap { series in
            let value = series.values[month]
            guard !value.isNaN else { return nil }
            let idx = allYears.firstIndex(where: { $0.id == series.id }) ?? 0
            return (String(series.year), ChartLabels.percent(value), lineColors[idx % lineColors.count])
        }
    }

    @ViewBuilder
    private var chartBody: some View {
        if #available(iOS 16.0, *) {
            Chart {
                ForEach(selectedSeries) { yearSeries in
                    let idx = allYears.firstIndex(where: { $0.id == yearSeries.id }) ?? 0
                    let color = lineColors[idx % lineColors.count]
                    let seriesPosition = selectedSeries.firstIndex(where: { $0.id == yearSeries.id }) ?? 0
                    ForEach(0..<12, id: \.self) { monthIdx in
                        let value = yearSeries.values[monthIdx]
                        if !value.isNaN {
                            LineMark(
                                x: .value("Month", monthIdx),
                                y: .value("Return", value),
                                series: .value("Year", String(yearSeries.year))
                            )
                            .foregroundStyle(color)
                            .interpolationMethod(.catmullRom)

                            PointMark(
                                x: .value("Month", monthIdx),
                                y: .value("Return", value)
                            )
                            .foregroundStyle(color)
                            .symbolSize(showAllLabels ? 32 : 18)
                            .annotation(position: seriesPosition == 0 ? .top : .bottom, spacing: 2) {
                                if showAllLabels {
                                    ChartValueBubble(text: ChartLabels.percent(value), color: color)
                                }
                            }
                        }
                    }
                }

                if let selectedMonthIdx, selectedMonthIdx >= 0, selectedMonthIdx < 12 {
                    RuleMark(x: .value("Selected", selectedMonthIdx))
                        .foregroundStyle(Color.secondary.opacity(0.35))
                        .lineStyle(StrokeStyle(lineWidth: 1, dash: [3, 3]))
                        .annotation(position: .top, spacing: 4) {
                            ChartSelectionCard(
                                title: monthAbbreviations[selectedMonthIdx],
                                rows: selectionRows(for: selectedMonthIdx)
                            )
                        }
                }
            }
            .chartXSelection(value: $selectedMonthIdx)
            .chartXAxis {
                AxisMarks(values: Array(0..<12)) { value in
                    AxisValueLabel {
                        if let idx = value.as(Int.self) {
                            Text(monthAbbreviations[idx])
                                .font(.caption2)
                        }
                    }
                }
            }
            .chartYAxis {
                AxisMarks { value in
                    AxisValueLabel {
                        if let d = value.as(Double.self) {
                            Text(String(format: "%+.1f%%", d))
                                .font(.caption2)
                        }
                    }
                    AxisGridLine()
                }
            }
            .frame(height: 220)
        } else {
            Text("iOS 16+ required for chart")
                .foregroundColor(.secondary)
                .frame(height: 220)
        }
    }

    // MARK: - Legend

    private var legend: some View {
        ScrollView(.horizontal, showsIndicators: false) {
            HStack(spacing: 16) {
                ForEach(selectedSeries) { yearSeries in
                    let idx = allYears.firstIndex(where: { $0.id == yearSeries.id }) ?? 0
                    HStack(spacing: 6) {
                        RoundedRectangle(cornerRadius: 2)
                            .fill(lineColors[idx % lineColors.count])
                            .frame(width: 20, height: 3)
                        Text(String(yearSeries.year))
                            .font(.caption)
                            .foregroundColor(.secondary)
                    }
                }
            }
        }
    }

    // MARK: - Year-end stats chips

    private var yearEndStatsRow: some View {
        ScrollView(.horizontal, showsIndicators: false) {
            HStack(spacing: 10) {
                ForEach(selectedSeries) { yearSeries in
                    let idx = allYears.firstIndex(where: { $0.id == yearSeries.id }) ?? 0
                    let color = lineColors[idx % lineColors.count]
                    let end = endValue(yearSeries)
                    VStack(alignment: .center, spacing: 3) {
                        Text(String(yearSeries.year))
                            .font(.caption2)
                            .foregroundColor(.secondary)
                        Text(String(format: "%+.1f%%", end.value) + (end.estimated ? "*" : ""))
                            .font(.subheadline.weight(.semibold))
                            .foregroundColor(end.value >= 0 ? color : .negativeRed)
                    }
                    .frame(minWidth: 60)
                    .padding(.horizontal, 12)
                    .padding(.vertical, 8)
                    .background(Color(.systemGray6))
                    .cornerRadius(8)
                }
            }
        }
    }

    // MARK: - 2-year comparison: KPIs (top) and table (bottom)

    @ViewBuilder
    private var comparisonStatsHeader: some View {
        let yearA = selectedSeries[0]
        let yearB = selectedSeries[1]
        let diffs = monthDiffs(yearA: yearA, yearB: yearB)
        let validDiffs = diffs.compactMap { $0 }
        let avgDiff = validDiffs.isEmpty ? 0 : validDiffs.reduce(0, +) / Double(validDiffs.count)
        let endAInfo = endValue(yearA)
        let endBInfo = endValue(yearB)
        let endDiff = endBInfo.value - endAInfo.value
        let endEstimated = endAInfo.estimated || endBInfo.estimated
        let bestDiff = validDiffs.max() ?? 0
        let worstDiff = validDiffs.min() ?? 0

        VStack(alignment: .leading, spacing: 8) {
            Text("\(yearA.year) vs \(yearB.year)")
                .font(.subheadline.weight(.semibold))

            ChartStatsRow(stats: [
                ChartStat(label: "Avg diff", value: String(format: "%+.1f%%", avgDiff),
                          color: avgDiff >= 0 ? .positiveGreen : .negativeRed),
                ChartStat(label: "End diff", value: String(format: "%+.1f%%", endDiff) + (endEstimated ? "*" : ""),
                          color: endDiff >= 0 ? .positiveGreen : .negativeRed),
                ChartStat(label: "Best month", value: String(format: "%+.1f%%", bestDiff),
                          color: .positiveGreen),
                ChartStat(label: "Worst month", value: String(format: "%+.1f%%", worstDiff),
                          color: .negativeRed),
            ])
        }
    }

    @ViewBuilder
    private var comparisonTable: some View {
        let yearA = selectedSeries[0]
        let yearB = selectedSeries[1]
        ChartDataTable(
            rows: comparisonTableRows(yearA: yearA, yearB: yearB),
            valueHeader: String(yearA.year),
            deltaPrevHeader: String(yearB.year),
            deltaFirstHeader: "Diff"
        )
    }

    // MARK: - Helpers

    /// Effective year-end value: the forecast (estimated) for the current incomplete year,
    /// otherwise the last month with real data.
    private func endValue(_ s: ChartsViewModel.YearSeries) -> (value: Double, estimated: Bool) {
        if let f = s.forecastEndValue { return (f, true) }
        return (s.values.last(where: { !$0.isNaN }) ?? 0, false)
    }

    private var hasEstimate: Bool {
        selectedSeries.contains { $0.forecastEndValue != nil }
    }

    private func monthDiffs(yearA: ChartsViewModel.YearSeries, yearB: ChartsViewModel.YearSeries) -> [Double?] {
        (0..<12).map { idx in
            let a = yearA.values[idx]
            let b = yearB.values[idx]
            guard !a.isNaN, !b.isNaN else { return nil }
            return b - a
        }
    }

    private func comparisonTableRows(
        yearA: ChartsViewModel.YearSeries,
        yearB: ChartsViewModel.YearSeries
    ) -> [ChartDataTableRow] {
        (0..<12).compactMap { idx in
            let valA = yearA.values[idx]
            let valB = yearB.values[idx]
            guard !valA.isNaN || !valB.isNaN else { return nil }
            let diff = (!valA.isNaN && !valB.isNaN) ? valB - valA : 0
            return ChartDataTableRow(
                label: monthAbbreviations[idx],
                value: valA.isNaN ? "—" : String(format: "%+.1f%%", valA),
                deltaPrev: valB.isNaN ? "—" : String(format: "%+.1f%%", valB),
                deltaFirst: (!valA.isNaN && !valB.isNaN) ? String(format: "%+.1f%%", diff) : "—",
                isPrevPositive: valB >= 0,
                isFirstPositive: diff >= 0
            )
        }
    }
}
