import SwiftUI
import Charts

/// 趋势列表的紧凑行:名称 + 条数/跨度 + mini sparkline + 最新值。
struct TrendRow: View {
    let bucket: SeriesBucket

    private var allPoints: [SeriesBucket.Point] {
        bucket.lines.flatMap(\.points)
    }

    private var pointCount: Int { allPoints.count }

    private var anyLatestAbnormal: Bool {
        bucket.lines.contains { ($0.latestPoint?.status ?? .normal) != .normal }
    }

    var body: some View {
        HStack(spacing: 12) {
            VStack(alignment: .leading, spacing: 3) {
                Text(bucket.title)
                    .font(.tjScaled( 15, weight: .semibold))
                    .foregroundStyle(Tj.Palette.text)
                    .lineLimit(1)
                Text(subtitle)
                    .font(.tjScaled( 11))
                    .foregroundStyle(Tj.Palette.text3)
            }

            Spacer(minLength: 8)

            sparkline
                .frame(width: 76, height: 34)

            VStack(alignment: .trailing, spacing: 2) {
                Text(latestValue)
                    .font(.tjScaled( 14, weight: .semibold, design: .monospaced))
                    .foregroundStyle(anyLatestAbnormal ? Tj.Palette.brick : Tj.Palette.text)
                    .lineLimit(1)
                Text(bucket.unit)
                    .font(.tjScaled( 9, design: .monospaced))
                    .foregroundStyle(Tj.Palette.text3)
            }
            .fixedSize()

            Image(systemName: "chevron.right")
                .font(.tjScaled( 12, weight: .medium))
                .foregroundStyle(Tj.Palette.text3)
        }
        .padding(14)
        .frame(maxWidth: .infinity)
        .tjCard(bordered: true)
    }

    private var sparkline: some View {
        Chart {
            // 单条线时,线下垫一层渐变面积,迷你图也更有体量、不发生硬。
            if bucket.lines.count == 1, let line = bucket.lines.first {
                ForEach(line.points) { p in
                    AreaMark(
                        x: .value("t", p.date),
                        y: .value(line.label ?? bucket.title, p.value)
                    )
                    .foregroundStyle(LinearGradient(
                        colors: [line.color.opacity(0.18), line.color.opacity(0)],
                        startPoint: .top, endPoint: .bottom))
                    .interpolationMethod(.monotone)
                }
            }
            ForEach(bucket.lines) { line in
                ForEach(line.points) { p in
                    LineMark(
                        x: .value("t", p.date),
                        y: .value(line.label ?? bucket.title, p.value),
                        series: .value("s", line.id)
                    )
                    .foregroundStyle(line.color)
                    // monotone + 圆角端点:迷你曲线更柔,无尖角无过冲。
                    .interpolationMethod(.monotone)
                    .lineStyle(StrokeStyle(lineWidth: 1.6, lineCap: .round, lineJoin: .round))
                }
            }
            // 最新点高亮
            ForEach(bucket.lines) { line in
                if let p = line.latestPoint {
                    PointMark(
                        x: .value("t", p.date),
                        y: .value("v", p.value)
                    )
                    .foregroundStyle(p.status == .normal ? line.color : Tj.Palette.brick)
                    .symbolSize(28)
                }
            }
        }
        .chartXAxis(.hidden)
        .chartYAxis(.hidden)
        .chartLegend(.hidden)
    }

    private var subtitle: String {
        "\(pointCount) 条 · 近 \(spanLabel)"
    }

    private var spanLabel: String {
        let dates = allPoints.map(\.date)
        guard let lo = dates.min(), let hi = dates.max() else { return "—" }
        let days = Calendar.current.dateComponents([.day], from: lo, to: hi).day ?? 0
        if days <= 0 { return String(appLoc: "今天") }
        if days < 30 { return String(appLoc: "\(days) 天") }
        if days < 365 { return String(appLoc: "\(days / 30) 个月") }
        return String(appLoc: "\(days / 365) 年")
    }

    private var latestValue: String {
        let parts = bucket.lines.compactMap { line -> String? in
            guard let p = line.latestPoint else { return nil }
            return formatValue(p.value)
        }
        return parts.joined(separator: "/")
    }

    private func formatValue(_ v: Double) -> String {
        v.truncatingRemainder(dividingBy: 1) == 0
            ? String(format: "%.0f", v)
            : String(format: "%.1f", v)
    }
}
