import SwiftUI
import Charts

struct LSVView: View {
    @Bindable var state: AppState

    var body: some View {
        VStack(spacing: 0) {
            controlsRow
            peakLabels
            Divider()
            GeometryReader { geo in
                if geo.size.width > 700 {
                    HSplitLayout(ratio: 0.55) {
                        voltammogramPlot
                    } trailing: {
                        lsvTable
                    }
                } else {
                    ScrollView {
                        VStack(spacing: 12) {
                            voltammogramPlot.frame(height: 350)
                            lsvTable.frame(height: 300)
                        }
                        .padding()
                    }
                }
            }
        }
    }

    // MARK: - Controls

    private var controlsRow: some View {
        ScrollView(.horizontal, showsIndicators: false) {
            HStack(spacing: 10) {
                LabeledField("Start mV", text: $state.lsvStartV, width: 80)
                LabeledField("Stop mV", text: $state.lsvStopV, width: 80)
                LabeledField("Scan mV/s", text: $state.lsvScanRate, width: 80)

                LabeledPicker("RTIA", selection: $state.lsvRtia, items: LpRtia.allCases) { $0.label }
                    .frame(width: 120)

                LabeledPicker("Density", selection: $state.lsvDensityMode, items: LsvDensityMode.allCases) { $0.rawValue }
                    .frame(width: 100)

                LabeledField("Value", text: $state.lsvDensity, width: 60)

                Text("\(state.lsvCalcPoints()) pts")
                    .font(.caption)
                    .foregroundStyle(.secondary)

                Button("Start LSV") { state.startLSV() }
                    .buttonStyle(ActionButtonStyle(color: .green))
            }
            .padding(.horizontal)
            .padding(.vertical, 8)
        }
    }

    // MARK: - Plot

    private var voltammogramPlot: some View {
        Group {
            if state.lsvPoints.isEmpty {
                Text("No data")
                    .foregroundStyle(Color(white: 0.4))
                    .frame(maxWidth: .infinity, maxHeight: .infinity)
                    .background(Color.black.opacity(0.3))
            } else {
                PlotContainer(title: "") {
                    Chart {
                        if let ref = state.lsvRef {
                            ForEach(Array(ref.enumerated()), id: \.offset) { _, pt in
                                LineMark(
                                    x: .value("V", Double(pt.vMv)),
                                    y: .value("I", Double(pt.iUa))
                                )
                                .foregroundStyle(Color.gray.opacity(0.5))
                                .lineStyle(StrokeStyle(lineWidth: 1.5))
                            }
                        }
                        ForEach(Array(state.lsvPoints.enumerated()), id: \.offset) { _, pt in
                            LineMark(
                                x: .value("V", Double(pt.vMv)),
                                y: .value("I", Double(pt.iUa))
                            )
                            .foregroundStyle(Color.yellow)
                            .lineStyle(StrokeStyle(lineWidth: 2))
                        }
                        ForEach(Array(state.lsvPoints.enumerated()), id: \.offset) { _, pt in
                            PointMark(
                                x: .value("V", Double(pt.vMv)),
                                y: .value("I", Double(pt.iUa))
                            )
                            .foregroundStyle(Color.yellow)
                            .symbolSize(16)
                        }
                        ForEach(Array(state.lsvPeaks.enumerated()), id: \.offset) { _, peak in
                            PointMark(
                                x: .value("V", Double(peak.vMv)),
                                y: .value("I", Double(peak.iUa))
                            )
                            .foregroundStyle(peakColor(peak.kind))
                            .symbolSize(100)
                            .symbol(.diamond)
                            RuleMark(x: .value("V", Double(peak.vMv)))
                                .foregroundStyle(peakColor(peak.kind).opacity(0.3))
                                .lineStyle(StrokeStyle(lineWidth: 1, dash: [4, 4]))
                        }
                    }
                    .chartXAxisLabel("V (mV)")
                    .chartYAxisLabel("I (uA)", position: .leading)
                    .chartXAxis {
                        AxisMarks { _ in
                            AxisGridLine(stroke: StrokeStyle(lineWidth: 0.5))
                                .foregroundStyle(Color.gray.opacity(0.3))
                            AxisValueLabel()
                                .font(.caption2)
                                .foregroundStyle(.secondary)
                        }
                    }
                    .chartYAxis {
                        AxisMarks(position: .leading) { _ in
                            AxisGridLine(stroke: StrokeStyle(lineWidth: 0.5))
                                .foregroundStyle(Color.gray.opacity(0.3))
                            AxisValueLabel()
                                .font(.caption2)
                                .foregroundStyle(Color.yellow)
                        }
                    }
                    .padding(8)
                }
            }
        }
        .background(Color.black.opacity(0.3))
        .clipShape(RoundedRectangle(cornerRadius: 8))
    }

    @ViewBuilder
    private var peakLabels: some View {
        if !state.lsvPeaks.isEmpty {
            HStack(spacing: 12) {
                ForEach(Array(state.lsvPeaks.enumerated()), id: \.offset) { _, peak in
                    let label: String = {
                        switch peak.kind {
                        case .freeCl:   return String(format: "Free: %.0fmV %.2fuA", peak.vMv, peak.iUa)
                        case .totalCl:  return String(format: "Total: %.0fmV %.2fuA", peak.vMv, peak.iUa)
                        case .crossover: return String(format: "X-over: %.0fmV", peak.vMv)
                        }
                    }()
                    Text(label)
                        .font(.caption)
                        .foregroundStyle(peakColor(peak.kind))
                }
            }
            .padding(.horizontal, 8)
            .padding(.vertical, 4)
        }
    }

    private func peakColor(_ kind: PeakKind) -> Color {
        switch kind {
        case .freeCl:   .green
        case .totalCl:  .orange
        case .crossover: .purple
        }
    }

    // MARK: - Table

    private var lsvTable: some View {
        MeasurementTable(
            columns: [
                MeasurementColumn(header: "V (mV)", width: 80, alignment: .trailing),
                MeasurementColumn(header: "I (uA)", width: 90, alignment: .trailing),
            ],
            rows: state.lsvPoints,
            cellText: { pt, col in
                switch col {
                case 0: String(format: "%.1f", pt.vMv)
                case 1: String(format: "%.3f", pt.iUa)
                default: ""
                }
            }
        )
    }
}
