import SwiftUI
import Charts

struct DrawdownChart: View {
    let data: [(date: Date, drawdown: Double)]
    @State private var zoom = ChartZoomModel()
    @State private var selectedDate: Date?

    private var showAllLabels: Bool { data.count <= ChartLabels.alwaysShowThreshold }
    private var selectedPoint: (date: Date, drawdown: Double)? {
        guard let selectedDate else { return nil }
        return data.min(by: {
            abs($0.date.timeIntervalSince(selectedDate)) < abs($1.date.timeIntervalSince(selectedDate))
        })
    }

    var maxDrawdown: Double {
        abs(data.map { $0.drawdown }.min() ?? 0)
    }

    var currentDrawdown: Double {
        abs(data.last?.drawdown ?? 0)
    }

    var body: some View {
        VStack(alignment: .leading, spacing: 16) {
            HStack {
                Text("Drawdown Analysis")
                    .font(.headline)

                Spacer()

                VStack(alignment: .trailing, spacing: 2) {
                    Text("Max Drawdown")
                        .font(.caption)
                        .foregroundColor(.secondary)
                    Text(String(format: "%.1f%%", maxDrawdown))
                        .font(.subheadline.weight(.semibold))
                        .foregroundColor(.negativeRed)
                }
            }

            Text("Shows percentage decline from peak values")
                .font(.caption)
                .foregroundColor(.secondary)

            if data.count >= 2 {
                Chart {
                    ForEach(data, id: \.date) { item in
                        AreaMark(
                            x: .value("Date", item.date),
                            y: .value("Drawdown", item.drawdown)
                        )
                        .foregroundStyle(
                            LinearGradient(
                                colors: [Color.negativeRed.opacity(0.5), Color.negativeRed.opacity(0.1)],
                                startPoint: .top,
                                endPoint: .bottom
                            )
                        )
                        .interpolationMethod(.catmullRom)

                        LineMark(
                            x: .value("Date", item.date),
                            y: .value("Drawdown", item.drawdown)
                        )
                        .foregroundStyle(Color.negativeRed)
                        .interpolationMethod(.catmullRom)

                        PointMark(
                            x: .value("Date", item.date),
                            y: .value("Drawdown", item.drawdown)
                        )
                        .foregroundStyle(Color.negativeRed)
                        .symbolSize(showAllLabels ? 36 : 20)
                        .annotation(position: .bottom, spacing: 3) {
                            if showAllLabels {
                                ChartValueBubble(text: ChartLabels.percent(item.drawdown), color: .negativeRed)
                            }
                        }
                    }

                    if let sel = selectedPoint {
                        RuleMark(x: .value("Selected", sel.date))
                            .foregroundStyle(Color.secondary.opacity(0.35))
                            .lineStyle(StrokeStyle(lineWidth: 1, dash: [3, 3]))
                        PointMark(
                            x: .value("Selected", sel.date),
                            y: .value("Drawdown", sel.drawdown)
                        )
                        .foregroundStyle(Color.negativeRed)
                        .symbolSize(70)
                        .annotation(position: .bottom, spacing: 4) {
                            ChartValueBubble(text: ChartLabels.percent(sel.drawdown), color: .negativeRed, prominent: true)
                        }
                    }
                }
                .chartXSelection(value: $selectedDate)
                .chartXAxis {
                    AxisMarks(values: .stride(by: .month, count: 2)) { value in
                        AxisValueLabel(format: .dateTime.month(.abbreviated))
                    }
                }
                .chartYAxis {
                    AxisMarks { value in
                        AxisGridLine()
                        AxisValueLabel {
                            if let doubleValue = value.as(Double.self) {
                                Text(String(format: "%.0f%%", doubleValue))
                                    .font(.caption)
                            }
                        }
                    }
                }
                .chartYScale(domain: (data.map { $0.drawdown }.min() ?? -50)...0)
                .frame(height: 250)
                .zoomableTimeSeries(dates: data.map(\.date), zoom: $zoom)

                // Statistics
                HStack(spacing: 20) {
                    DrawdownStatView(
                        title: "Current",
                        value: String(format: "%.1f%%", currentDrawdown),
                        isHighlighted: currentDrawdown > maxDrawdown * 0.8
                    )

                    DrawdownStatView(
                        title: "Maximum",
                        value: String(format: "%.1f%%", maxDrawdown),
                        isHighlighted: true
                    )

                    DrawdownStatView(
                        title: "Average",
                        value: String(format: "%.1f%%", averageDrawdown),
                        isHighlighted: false
                    )
                }
                .padding(.top, 8)
                ChartDataTable(
                    rows: drawdownTableRows,
                    valueHeader: "Drawdown",
                    deltaPrevHeader: "Δ prev",
                    deltaFirstHeader: "Δ first"
                )
                .padding(.top, 4)
            } else {
                Text("Not enough data for drawdown analysis")
                    .foregroundColor(.secondary)
                    .frame(height: 250)
                    .frame(maxWidth: .infinity)
            }
        }
        .padding()
        .background(Color(.systemBackground))
        .cornerRadius(AppConstants.UI.cornerRadius)
        .shadow(color: .black.opacity(0.05), radius: 8, y: 2)
    }

    private var averageDrawdown: Double {
        guard !data.isEmpty else { return 0 }
        let sum = data.reduce(0.0) { $0 + abs($1.drawdown) }
        return sum / Double(data.count)
    }

    private var drawdownTableRows: [ChartDataTableRow] {
        data.enumerated().map { idx, point in
            let val = abs(point.drawdown)
            let prevVal = idx > 0 ? abs(data[idx - 1].drawdown) : val
            let firstVal = abs(data.first?.drawdown ?? val)
            let deltaPrev = -(val - prevVal)  // negative delta = improvement (less drawdown)
            let deltaFirst = -(val - firstVal)
            return ChartDataTableRow(
                label: chartTableDateLabel(point.date),
                value: String(format: "%.1f%%", val),
                deltaPrev: idx > 0 ? String(format: "%+.1f%%", deltaPrev) : nil,
                deltaFirst: idx > 0 ? String(format: "%+.1f%%", deltaFirst) : nil,
                isPrevPositive: deltaPrev >= 0,
                isFirstPositive: deltaFirst >= 0
            )
        }
    }
}

struct DrawdownStatView: View {
    let title: String
    let value: String
    let isHighlighted: Bool

    var body: some View {
        VStack(spacing: 4) {
            Text(title)
                .font(.caption)
                .foregroundColor(.secondary)

            Text(value)
                .font(.subheadline.weight(.semibold))
                .foregroundColor(isHighlighted ? .negativeRed : .primary)
        }
        .frame(maxWidth: .infinity)
    }
}

// MARK: - Volatility Chart View

struct VolatilityChartView: View {
    let data: [(date: Date, volatility: Double)]
    @State private var zoom = ChartZoomModel()
    @State private var selectedDate: Date?

    private var showAllLabels: Bool { data.count <= ChartLabels.alwaysShowThreshold }
    private var selectedPoint: (date: Date, volatility: Double)? {
        guard let selectedDate else { return nil }
        return data.min(by: {
            abs($0.date.timeIntervalSince(selectedDate)) < abs($1.date.timeIntervalSince(selectedDate))
        })
    }

    var currentVolatility: Double {
        data.last?.volatility ?? 0
    }

    var averageVolatility: Double {
        guard !data.isEmpty else { return 0 }
        return data.reduce(0.0) { $0 + $1.volatility } / Double(data.count)
    }

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

                Spacer()
            }

            Text("Measures price variability over time")
                .font(.caption)
                .foregroundColor(.secondary)

            if data.count >= 2 {
                Chart {
                    ForEach(data, id: \.date) { item in
                        LineMark(
                            x: .value("Date", item.date),
                            y: .value("Volatility", item.volatility)
                        )
                        .foregroundStyle(Color.appPrimary)
                        .interpolationMethod(.catmullRom)

                        AreaMark(
                            x: .value("Date", item.date),
                            y: .value("Volatility", item.volatility)
                        )
                        .foregroundStyle(
                            LinearGradient(
                                colors: [Color.appPrimary.opacity(0.3), Color.appPrimary.opacity(0.0)],
                                startPoint: .top,
                                endPoint: .bottom
                            )
                        )
                        .interpolationMethod(.catmullRom)

                        PointMark(
                            x: .value("Date", item.date),
                            y: .value("Volatility", item.volatility)
                        )
                        .foregroundStyle(Color.appPrimary)
                        .symbolSize(showAllLabels ? 36 : 20)
                        .annotation(position: .top, spacing: 3) {
                            if showAllLabels {
                                ChartValueBubble(text: String(format: "%.1f%%", item.volatility))
                            }
                        }
                    }

                    // Average line
                    RuleMark(y: .value("Average", averageVolatility))
                        .foregroundStyle(Color.gray.opacity(0.5))
                        .lineStyle(StrokeStyle(lineWidth: 1, dash: [5, 5]))
                        .annotation(position: .top, alignment: .leading) {
                            Text("Avg: \(String(format: "%.1f%%", averageVolatility))")
                                .font(.caption2)
                                .foregroundColor(.secondary)
                        }

                    if let sel = selectedPoint {
                        RuleMark(x: .value("Selected", sel.date))
                            .foregroundStyle(Color.secondary.opacity(0.35))
                            .lineStyle(StrokeStyle(lineWidth: 1, dash: [3, 3]))
                        PointMark(
                            x: .value("Selected", sel.date),
                            y: .value("Volatility", sel.volatility)
                        )
                        .foregroundStyle(Color.appPrimary)
                        .symbolSize(70)
                        .annotation(position: .top, spacing: 4) {
                            ChartValueBubble(text: String(format: "%.1f%%", sel.volatility), prominent: true)
                        }
                    }
                }
                .chartXSelection(value: $selectedDate)
                .chartXAxis {
                    AxisMarks(values: .stride(by: .month, count: 2)) { value in
                        AxisValueLabel(format: .dateTime.month(.abbreviated))
                    }
                }
                .chartYAxis {
                    AxisMarks { value in
                        AxisGridLine()
                        AxisValueLabel {
                            if let doubleValue = value.as(Double.self) {
                                Text(String(format: "%.0f%%", doubleValue))
                                    .font(.caption)
                            }
                        }
                    }
                }
                .frame(height: 250)
                .zoomableTimeSeries(dates: data.map(\.date), zoom: $zoom)

                ChartStatsRow(stats: [
                    ChartStat(label: "Current", value: String(format: "%.1f%%", currentVolatility), color: volatilityColor(currentVolatility)),
                    ChartStat(label: "Max", value: String(format: "%.1f%%", data.map { $0.volatility }.max() ?? 0), color: .negativeRed),
                    ChartStat(label: "Min", value: String(format: "%.1f%%", data.map { $0.volatility }.min() ?? 0), color: .positiveGreen),
                    ChartStat(label: "Average", value: String(format: "%.1f%%", averageVolatility), color: .secondary),
                ])
                .padding(.top, 8)
                ChartDataTable(
                    rows: volatilityTableRows,
                    valueHeader: "Volatility",
                    deltaPrevHeader: "Δ prev",
                    deltaFirstHeader: nil
                )
            } else {
                Text("Not enough data for volatility analysis")
                    .foregroundColor(.secondary)
                    .frame(height: 250)
                    .frame(maxWidth: .infinity)
            }
        }
        .padding()
        .background(Color(.systemBackground))
        .cornerRadius(AppConstants.UI.cornerRadius)
        .shadow(color: .black.opacity(0.05), radius: 8, y: 2)
    }

    private func volatilityColor(_ volatility: Double) -> Color {
        switch volatility {
        case 0..<10:
            return .positiveGreen
        case 10..<20:
            return .appWarning
        default:
            return .negativeRed
        }
    }

    private var volatilityTableRows: [ChartDataTableRow] {
        data.enumerated().map { idx, point in
            let prevVal = idx > 0 ? data[idx - 1].volatility : point.volatility
            let delta = point.volatility - prevVal
            return ChartDataTableRow(
                label: chartTableDateLabel(point.date),
                value: String(format: "%.1f%%", point.volatility),
                deltaPrev: idx > 0 ? String(format: "%+.1f%%", delta) : nil,
                deltaFirst: nil,
                isPrevPositive: delta <= 0,
                isFirstPositive: false
            )
        }
    }
}

struct VolatilityLevelView: View {
    let level: String
    let range: String
    let color: Color

    var body: some View {
        HStack(spacing: 4) {
            Circle()
                .fill(color)
                .frame(width: 8, height: 8)

            VStack(alignment: .leading, spacing: 0) {
                Text(level)
                    .font(.caption2)
                Text(range)
                    .font(.caption2)
                    .foregroundColor(.secondary)
            }
        }
    }
}

#Preview {
    let drawdownData: [(date: Date, drawdown: Double)] = [
        (Date().adding(months: -6), -5),
        (Date().adding(months: -5), -8),
        (Date().adding(months: -4), -3),
        (Date().adding(months: -3), -15),
        (Date().adding(months: -2), -10),
        (Date().adding(months: -1), -7),
        (Date(), -4)
    ]

    let volatilityData: [(date: Date, volatility: Double)] = [
        (Date().adding(months: -6), 12),
        (Date().adding(months: -5), 15),
        (Date().adding(months: -4), 10),
        (Date().adding(months: -3), 22),
        (Date().adding(months: -2), 18),
        (Date().adding(months: -1), 14),
        (Date(), 11)
    ]

    return VStack(spacing: 20) {
        DrawdownChart(data: drawdownData)
        VolatilityChartView(data: volatilityData)
    }
    .padding()
}
