import SwiftUI
import Charts

struct AllocationSimulatorView: View {
    @ObservedObject var viewModel: ChartsViewModel

    var body: some View {
        VStack(alignment: .leading, spacing: 16) {
            Text("Allocation Simulator")
                .font(.headline)

            if viewModel.simulatorSources.isEmpty {
                emptyStateView
            } else {
                allocationCard
                chartSection
            }
        }
        .padding()
        .background(Color(.systemBackground))
        .cornerRadius(AppConstants.UI.cornerRadius)
        .shadow(color: .black.opacity(0.05), radius: 8, y: 2)
    }

    // MARK: - Empty State

    private var emptyStateView: some View {
        VStack(spacing: 12) {
            Image(systemName: "slider.horizontal.3")
                .font(.system(size: 36))
                .foregroundColor(.secondary)
            Text("No sources available")
                .font(.subheadline)
                .foregroundColor(.secondary)
        }
        .frame(maxWidth: .infinity)
        .frame(height: 300)
    }

    // MARK: - Allocation Card

    private var allocationCard: some View {
        VStack(alignment: .leading, spacing: 12) {
            HStack {
                Text("Adjust Allocation")
                    .font(.subheadline.weight(.semibold))
                Spacer()
                totalAllocationBadge
                resetButton
            }

            ForEach(Array(viewModel.simulatorSources.enumerated()), id: \.element.id) { index, source in
                sourceSliderRow(index: index, source: source)
            }
        }
        .padding(12)
        .background(Color(.systemGray6))
        .cornerRadius(10)
    }

    private var totalAllocationBadge: some View {
        let total = viewModel.simulatorSources.reduce(0) { $0 + $1.simulatedPct }
        let isNear100 = abs(total - 100) < 5
        return Text(String(format: "%.0f%%", total))
            .font(.caption.weight(.semibold))
            .padding(.horizontal, 8)
            .padding(.vertical, 3)
            .background(isNear100 ? Color.green.opacity(0.15) : Color.orange.opacity(0.15))
            .foregroundColor(isNear100 ? .green : .orange)
            .cornerRadius(8)
    }

    private var resetButton: some View {
        Button {
            var updated = viewModel.simulatorSources
            for i in updated.indices {
                updated[i] = ChartsViewModel.SimulatorSource(
                    id: updated[i].id,
                    name: updated[i].name,
                    currentPct: updated[i].currentPct,
                    simulatedPct: updated[i].currentPct,
                    colorHex: updated[i].colorHex
                )
            }
            viewModel.simulatorSources = updated
        } label: {
            Image(systemName: "arrow.counterclockwise")
                .font(.caption)
                .foregroundColor(.secondary)
        }
        .buttonStyle(.plain)
    }

    private func sourceSliderRow(index: Int, source: ChartsViewModel.SimulatorSource) -> some View {
        VStack(spacing: 4) {
            HStack {
                Circle()
                    .fill(Color(hex: source.colorHex) ?? .gray)
                    .frame(width: 8, height: 8)
                Text(source.name)
                    .font(.caption.weight(.medium))
                    .lineLimit(1)
                Spacer()
                Text(String(format: "%.0f%%", source.simulatedPct))
                    .font(.caption.weight(.semibold))
                    .foregroundColor(.primary)
                    .frame(width: 36, alignment: .trailing)
                Text(String(format: "(%.0f%%)", source.currentPct))
                    .font(.caption2)
                    .foregroundColor(.secondary)
            }

            Slider(
                value: Binding<Double>(
                    get: { source.simulatedPct },
                    set: { newValue in
                        var updated = viewModel.simulatorSources
                        if index < updated.count {
                            updated[index] = ChartsViewModel.SimulatorSource(
                                id: source.id,
                                name: source.name,
                                currentPct: source.currentPct,
                                simulatedPct: newValue,
                                colorHex: source.colorHex
                            )
                            viewModel.simulatorSources = updated
                        }
                    }
                ),
                in: 0...100,
                step: 1
            )
            .tint(Color(hex: source.colorHex) ?? .appPrimary)
        }
    }

    // MARK: - Chart Section

    private var chartSection: some View {
        VStack(alignment: .leading, spacing: 8) {
            if viewModel.simulatorActualData.isEmpty && viewModel.simulatorData.isEmpty {
                Text("Not enough data to simulate.")
                    .font(.subheadline)
                    .foregroundColor(.secondary)
                    .frame(height: 220)
            } else {
                simulationChart
                chartLegend
            }
        }
    }

    private var simulationChart: some View {
        Chart {
            ForEach(viewModel.simulatorActualData, id: \.date) { item in
                LineMark(
                    x: .value("Date", item.date),
                    y: .value("Value", item.value),
                    series: .value("Series", "Actual")
                )
                .foregroundStyle(Color.blue)
                .interpolationMethod(.catmullRom)
            }

            ForEach(viewModel.simulatorData, id: \.date) { item in
                LineMark(
                    x: .value("Date", item.date),
                    y: .value("Value", item.value),
                    series: .value("Series", "Simulated")
                )
                .foregroundStyle(Color.orange)
                .lineStyle(StrokeStyle(lineWidth: 2, dash: [6, 3]))
                .interpolationMethod(.catmullRom)
            }
        }
        .chartXAxis {
            AxisMarks(values: .stride(by: .month, count: xAxisStride)) { value in
                AxisGridLine(stroke: StrokeStyle(lineWidth: 0.5, dash: [3, 3]))
                    .foregroundStyle(Color.secondary.opacity(0.2))
                AxisValueLabel(format: .dateTime.month(.abbreviated).year(.twoDigits))
                    .font(.caption2)
            }
        }
        .chartYAxis {
            AxisMarks(position: .leading) { value in
                AxisValueLabel {
                    if let d = value.as(Double.self) {
                        Text(String(format: "%.0f", d))
                            .font(.caption2)
                    }
                }
                AxisGridLine(stroke: StrokeStyle(lineWidth: 0.5, dash: [3, 3]))
                    .foregroundStyle(Color.secondary.opacity(0.15))
            }
        }
        .frame(height: 220)
        .drawingGroup()
    }

    private var chartLegend: some View {
        HStack(spacing: 20) {
            legendItem(color: .blue, label: "Actual", dashed: false)
            legendItem(color: .orange, label: "Simulated", dashed: true)
            Spacer()
        }
    }

    private func legendItem(color: Color, label: String, dashed: Bool) -> some View {
        HStack(spacing: 6) {
            if dashed {
                HStack(spacing: 2) {
                    RoundedRectangle(cornerRadius: 2)
                        .fill(color)
                        .frame(width: 8, height: 3)
                    RoundedRectangle(cornerRadius: 2)
                        .fill(color)
                        .frame(width: 8, height: 3)
                }
            } else {
                RoundedRectangle(cornerRadius: 2)
                    .fill(color)
                    .frame(width: 20, height: 3)
            }
            Text(label)
                .font(.caption)
                .foregroundColor(.secondary)
        }
    }

    // MARK: - Helpers

    private var xAxisStride: Int {
        let count = max(viewModel.simulatorActualData.count, viewModel.simulatorData.count)
        switch count {
        case ...6: return 1
        case ...12: return 2
        case ...24: return 3
        default: return 6
        }
    }
}
