import Charts
import SwiftUI
import TokenLensCore

struct TrendChart: View {
    let summary: UsageSummary
    let mode: TrendMode

    private var points: [DailyPoint] {
        summary.trendPoints(mode: mode)
    }

    private var chartPoints: [ProviderTrendPoint] {
        points.flatMap { point in
            Provider.allCases.map { provider in
                ProviderTrendPoint(
                    mode: mode,
                    date: point.date,
                    provider: provider,
                    tokens: point.values[provider, default: 0]
                )
            }
        }
    }

    private var maxValue: Int {
        max(1, chartPoints.map(\.tokens).max() ?? 1)
    }

    var body: some View {
        Chart(chartPoints) { point in
            LineMark(
                x: .value("日期", point.date),
                y: .value("Tokens", point.tokens),
                series: .value("工具", point.provider.rawValue)
            )
            .interpolationMethod(.linear)
            .lineStyle(StrokeStyle(lineWidth: 3.5, lineCap: .round, lineJoin: .round))
            .foregroundStyle(by: .value("工具", point.provider.rawValue))

            AreaMark(
                x: .value("日期", point.date),
                y: .value("Tokens", point.tokens),
                series: .value("工具", point.provider.rawValue)
            )
            .interpolationMethod(.linear)
            .foregroundStyle(by: .value("工具", point.provider.rawValue))
            .opacity(point.provider == .codex ? 0.10 : 0.03)
        }
        .chartForegroundStyleScale(providerStyleScale)
        .chartLegend(position: .bottom, alignment: .center, spacing: 18)
        .chartYScale(domain: 0...(Double(maxValue) * 1.08))
        .chartPlotStyle { plot in
            plot.clipped()
        }
        .chartYAxis {
            AxisMarks(position: .leading, values: .automatic(desiredCount: 5)) { value in
                AxisGridLine(stroke: StrokeStyle(lineWidth: 1))
                    .foregroundStyle(.white.opacity(0.08))
                AxisValueLabel {
                    if let tokens = value.as(Double.self) {
                        Text(TokenFormatter.format(Int(tokens)))
                            .foregroundStyle(.secondary)
                    }
                }
            }
        }
        .chartXAxis {
            AxisMarks(values: .automatic(desiredCount: mode == .daily ? 6 : 5)) { value in
                AxisGridLine()
                    .foregroundStyle(.clear)
                AxisValueLabel {
                    if let date = value.as(Date.self) {
                        Text(axisLabel(for: date))
                            .foregroundStyle(.secondary)
                    }
                }
            }
        }
        .frame(height: 235)
        .animation(.spring(response: 0.42, dampingFraction: 0.88), value: mode)
    }

    private func axisLabel(for date: Date) -> String {
        switch mode {
        case .daily:
            return date.formatted(.dateTime.hour(.twoDigits(amPM: .omitted)))
        case .weekly:
            return date.formatted(.dateTime.month(.twoDigits).day(.twoDigits))
        case .monthly:
            return date.formatted(.dateTime.month(.twoDigits).day(.twoDigits))
        case .yearly:
            return date.formatted(.dateTime.year(.twoDigits).month(.twoDigits))
        }
    }
}

struct UsageShare: View {
    let summary: UsageSummary

    var total: Int {
        Provider.allCases.reduce(0) { $0 + (summary.providerTotals[$1]?.totalTokens ?? 0) }
    }

    private var visibleProviders: [Provider] {
        let active = Provider.allCases.filter {
            (summary.providerTotals[$0]?.totalTokens ?? 0) > 0
        }
        return active.isEmpty ? Provider.allCases : active
    }

    var body: some View {
        HStack(spacing: 28) {
            VStack(spacing: 10) {
                PieChartView(summary: summary)
                    .frame(width: 190, height: 190)
                HStack(spacing: 8) {
                    Text("本月")
                        .foregroundStyle(.secondary)
                    Text(TokenFormatter.format(total))
                        .fontWeight(.bold)
                        .monospacedDigit()
                }
                .font(.system(size: 14, weight: .semibold, design: .rounded))
            }
            VStack(spacing: 12) {
                ForEach(visibleProviders, id: \.self) { provider in
                    let providerTotal = summary.providerTotals[provider]?.totalTokens ?? 0
                    let percent = total > 0 ? Int((Double(providerTotal) / Double(total) * 100).rounded()) : 0
                    HStack {
                        Circle().fill(provider.color).frame(width: 10, height: 10)
                        VStack(alignment: .leading, spacing: 2) {
                            Text(provider.rawValue)
                                .font(.system(size: 15, weight: .semibold))
                            Text("\(TokenFormatter.format(providerTotal)) Tokens")
                                .font(.system(size: 12, weight: .medium))
                                .foregroundStyle(.secondary)
                        }
                        Spacer()
                        Text("\(percent)%")
                            .font(.system(size: 19, weight: .bold, design: .rounded))
                    }
                }
            }
        }
        .frame(height: 235)
    }
}

struct PieChartView: View {
    let summary: UsageSummary

    var total: Int {
        Provider.allCases.reduce(0) { $0 + (summary.providerTotals[$1]?.totalTokens ?? 0) }
    }

    private var slices: [ProviderSlice] {
        Provider.allCases.map { provider in
            ProviderSlice(
                provider: provider,
                tokens: summary.providerTotals[provider]?.totalTokens ?? 0
            )
        }
    }

    var body: some View {
        Chart(slices) { slice in
            SectorMark(
                angle: .value("Tokens", max(slice.tokens, 0)),
                angularInset: 1.8
            )
            .cornerRadius(6)
            .foregroundStyle(by: .value("工具", slice.provider.rawValue))
            .opacity(total > 0 && slice.tokens > 0 ? 1 : 0)
        }
        .chartForegroundStyleScale(providerStyleScale)
        .chartLegend(.hidden)
        .chartBackground { _ in
            if total == 0 {
                Circle()
                    .fill(.white.opacity(0.10))
            }
        }
        .shadow(color: .purple.opacity(0.24), radius: 18, y: 12)
    }
}

struct ToolBreakdown: View {
    let rows: [ToolRow]
    @Binding var selection: String
    private let visibleRowLimit = ToolBreakdownLayout.visibleRowLimit

    private var visibleRowCount: Int {
        min(max(rows.count, 1), visibleRowLimit)
    }

    private var rowViewportHeight: CGFloat {
        CGFloat(visibleRowCount) * ToolBreakdownLayout.rowHeight
    }

    private var providerSignature: String {
        rows.map { $0.provider.rawValue }.joined(separator: "|")
    }

    var body: some View {
        GlassCard {
            VStack(spacing: 0) {
                HStack {
                    Text("工具明细")
                        .font(.system(size: 21, weight: .bold, design: .rounded))
                    Spacer()
                    NativeMenuPicker(selection: $selection, options: ["全部工具"] + Provider.allCases.map(\.rawValue))
                        .frame(width: 142)
                }
                .padding(.bottom, 12)

                VStack(spacing: 0) {
                    ToolBreakdownHeader()
                    ScrollView(showsIndicators: rows.count > visibleRowLimit) {
                        LazyVStack(spacing: 0) {
                            if rows.isEmpty {
                                Text("暂无工具数据")
                                    .font(.system(size: 14, weight: .semibold))
                                    .foregroundStyle(.secondary)
                                    .frame(maxWidth: .infinity)
                                    .frame(height: ToolBreakdownLayout.rowHeight)
                            } else {
                                ForEach(rows) { row in
                                    ToolBreakdownRow(row: row)
                                    if row.id != rows.last?.id {
                                        Divider()
                                            .overlay(.white.opacity(0.08))
                                    }
                                }
                            }
                        }
                    }
                    .id(providerSignature)
                    .frame(height: rowViewportHeight)
                }
                .padding(.horizontal, 12)
                .padding(.vertical, 5)
                .background(.white.opacity(0.035), in: RoundedRectangle(cornerRadius: 18, style: .continuous))
                .overlay(RoundedRectangle(cornerRadius: 18, style: .continuous).stroke(.white.opacity(0.08)))
            }
            .frame(maxHeight: .infinity, alignment: .top)
        }
    }
}

private enum ToolBreakdownLayout {
    static let visibleRowLimit = 3
    static let rowHeight: CGFloat = 54
    static let headerHeight: CGFloat = 38
}

private enum ToolBreakdownColumns {
    static let spacing: CGFloat = 16

    static func widths(totalWidth: CGFloat) -> ToolBreakdownColumnWidths {
        let contentWidth = max(0, totalWidth - spacing * 5)
        return ToolBreakdownColumnWidths(
            tool: contentWidth * 0.24,
            metric: contentWidth * 0.15,
            trend: contentWidth * 0.16
        )
    }
}

private struct ToolBreakdownColumnWidths {
    let tool: CGFloat
    let metric: CGFloat
    let trend: CGFloat
}

private struct ToolBreakdownHeader: View {
    var body: some View {
        GeometryReader { proxy in
            let widths = ToolBreakdownColumns.widths(totalWidth: proxy.size.width)
            HStack(spacing: ToolBreakdownColumns.spacing) {
                header("工具名称", width: widths.tool, alignment: .leading)
                header("输入", width: widths.metric)
                header("输出", width: widths.metric)
                header("缓存", width: widths.metric)
                header("总量", width: widths.metric)
                header("趋势", width: widths.trend)
            }
            .frame(width: proxy.size.width, height: proxy.size.height)
        }
        .frame(maxWidth: .infinity)
        .padding(.horizontal, 14)
        .frame(height: ToolBreakdownLayout.headerHeight)
        .overlay(alignment: .bottom) {
            Rectangle()
                .fill(.white.opacity(0.10))
                .frame(height: 1)
        }
    }

    private func header(_ text: String, width: CGFloat, alignment: Alignment = .center) -> some View {
        Text(text)
            .font(.system(size: 13, weight: .bold))
            .foregroundStyle(.secondary)
            .frame(width: width, alignment: alignment)
    }
}

private struct ToolBreakdownRow: View {
    let row: ToolRow

    var body: some View {
        GeometryReader { proxy in
            let widths = ToolBreakdownColumns.widths(totalWidth: proxy.size.width)
            HStack(spacing: ToolBreakdownColumns.spacing) {
                providerCell(row.provider)
                    .frame(width: widths.tool, alignment: .leading)
                metric(TokenFormatter.format(row.inputTokens), width: widths.metric)
                metric(TokenFormatter.format(row.outputTokens), width: widths.metric)
                metric(TokenFormatter.format(row.cachedTokens), width: widths.metric)
                metric(TokenFormatter.format(row.totalTokens), width: widths.metric)
                Sparkline(provider: row.provider, values: row.trendTokens)
                    .frame(width: 112, height: 30)
                    .frame(width: widths.trend, alignment: .center)
            }
            .frame(width: proxy.size.width, height: proxy.size.height)
        }
        .frame(maxWidth: .infinity)
        .padding(.horizontal, 14)
        .frame(height: ToolBreakdownLayout.rowHeight)
    }

    private func metric(_ text: String, width: CGFloat) -> some View {
        Text(text)
            .font(.system(size: 16, weight: .bold, design: .rounded))
            .monospacedDigit()
            .lineLimit(1)
            .minimumScaleFactor(0.68)
            .frame(width: width, alignment: .center)
    }

    private func providerBadge(_ provider: Provider) -> some View {
        RoundedRectangle(cornerRadius: 9)
            .fill(provider.color.gradient)
            .frame(width: 30, height: 30)
            .overlay {
                Text(String(provider.rawValue.prefix(1)))
                    .font(.system(size: 13, weight: .bold))
            }
    }

    private func providerCell(_ provider: Provider) -> some View {
        HStack(spacing: 12) {
            providerBadge(provider)
            Text(provider.rawValue)
                .font(.system(size: 15, weight: .semibold))
        }
        .frame(maxWidth: .infinity, alignment: .leading)
    }
}

struct Sparkline: View {
    let provider: Provider
    let values: [Int]

    var body: some View {
        Chart(points) { point in
            LineMark(
                x: .value("序号", point.index),
                y: .value("趋势", point.value)
            )
            .interpolationMethod(.linear)
            .lineStyle(StrokeStyle(lineWidth: 3, lineCap: .round, lineJoin: .round))
            .foregroundStyle(provider.color)
        }
        .chartXAxis(.hidden)
        .chartYAxis(.hidden)
        .chartLegend(.hidden)
        .chartPlotStyle { plot in
            plot.background(.clear)
        }
        .chartYScale(domain: yDomain)
    }

    private var points: [SparkPoint] {
        let source = values.isEmpty ? [0, 0] : values
        let padded = source.count == 1 ? [0, source[0]] : source
        return padded.enumerated().map {
            SparkPoint(index: $0.offset, value: $0.element)
        }
    }

    private var yDomain: ClosedRange<Int> {
        let maxValue = max(1, points.map(\.value).max() ?? 1)
        return 0...maxValue
    }
}

private struct ProviderTrendPoint: Identifiable, Hashable {
    var id: String {
        "\(mode.rawValue)-\(Int(date.timeIntervalSince1970))-\(provider.rawValue)"
    }

    let mode: TrendMode
    let date: Date
    let provider: Provider
    let tokens: Int
}

private struct ProviderSlice: Identifiable, Hashable {
    let id = UUID()
    let provider: Provider
    let tokens: Int
}

private struct SparkPoint: Identifiable, Hashable {
    let id = UUID()
    let index: Int
    let value: Int
}

private var providerStyleScale: KeyValuePairs<String, Color> {
    [
        Provider.claude.rawValue: Provider.claude.color,
        Provider.codex.rawValue: Provider.codex.color,
        Provider.gemini.rawValue: Provider.gemini.color,
        Provider.hermes.rawValue: Provider.hermes.color,
        Provider.opencode.rawValue: Provider.opencode.color
    ]
}

struct TokenActivityHeatmap: View {
    let summary: UsageSummary
    @State private var mode = "每日"
    @State private var hoveredDay: HeatmapDay?
    @State private var tooltipPosition: CGPoint?

    private let cellWidth: CGFloat = 10
    private let cellHeight: CGFloat = 18
    private let cellSpacing: CGFloat = 3
    private let modes = ["每日", "每周", "累计"]

    private var weeks: [[HeatmapDay]] {
        makeHeatmapWeeks(mode: mode)
    }

    private var maxValue: Int {
        max(1, weeks.flatMap { $0 }.map(\.value).max() ?? 1)
    }

    private var selectedDay: HeatmapDay? {
        hoveredDay ?? weeks.flatMap { $0 }.last { !$0.isFuture }
    }

    private var visibleDays: [HeatmapDay] {
        weeks.flatMap { $0 }.filter { !$0.isFuture }
    }

    private var activeDays: Int {
        visibleDays.filter { $0.dailyTotal > 0 }.count
    }

    private var averageTokens: Int {
        guard !visibleDays.isEmpty else { return 0 }
        return visibleDays.reduce(0) { $0 + $1.dailyTotal } / visibleDays.count
    }

    private var peakTokens: Int {
        visibleDays.map(\.dailyTotal).max() ?? 0
    }

    var body: some View {
        GlassCard {
            VStack(alignment: .leading, spacing: 12) {
                HStack(alignment: .firstTextBaseline) {
                    VStack(alignment: .leading, spacing: 3) {
                        Text("Token 活动")
                            .font(.system(size: 21, weight: .bold, design: .rounded))
                        if let selectedDay {
                            Text("\(selectedDay.date.formatted(.dateTime.month().day())) · \(TokenFormatter.format(selectedDay.dailyTotal)) Tokens")
                                .font(.system(size: 13, weight: .semibold))
                                .foregroundStyle(.secondary)
                                .monospacedDigit()
                        }
                    }
                    Spacer()
                    HStack(spacing: 12) {
                        ForEach(modes, id: \.self) { item in
                            Button(item) {
                                withAnimation(.smooth(duration: 0.22)) {
                                    mode = item
                                }
                            }
                            .buttonStyle(.plain)
                            .font(.system(size: 13, weight: mode == item ? .bold : .semibold))
                            .foregroundStyle(mode == item ? .primary : .secondary)
                        }
                    }
                }

                heatmapGrid
                    .frame(maxWidth: .infinity, alignment: .center)
                    .animation(.smooth(duration: 0.25), value: weeks)

                HStack {
                    Text(monthRangeText)
                        .font(.system(size: 12, weight: .semibold))
                        .foregroundStyle(.secondary)
                    Spacer()
                    HeatmapLegend { value in
                        color(for: HeatmapDay(date: summary.generatedAt, value: value, dailyTotal: value, isFuture: false))
                    }
                }

                HStack(spacing: 8) {
                    HeatmapStat(title: "活跃", value: "\(activeDays) 天")
                    HeatmapStat(title: "日均", value: TokenFormatter.format(averageTokens))
                    HeatmapStat(title: "峰值", value: TokenFormatter.format(peakTokens))
                }
                Spacer(minLength: 0)
            }
            .frame(maxHeight: .infinity, alignment: .top)
        }
    }

    private var heatmapGrid: some View {
        let gridWidth = CGFloat(weeks.count) * cellWidth + CGFloat(max(weeks.count - 1, 0)) * cellSpacing
        let gridHeight = CGFloat(7) * cellHeight + CGFloat(6) * cellSpacing

        return ZStack(alignment: .topLeading) {
            HStack(alignment: .top, spacing: cellSpacing) {
                ForEach(Array(weeks.enumerated()), id: \.offset) { weekIndex, week in
                    VStack(spacing: cellSpacing) {
                        ForEach(Array(week.enumerated()), id: \.element.id) { dayIndex, day in
                            RoundedRectangle(cornerRadius: 5, style: .continuous)
                                .fill(color(for: day))
                                .frame(width: cellWidth, height: cellHeight)
                                .overlay {
                                    RoundedRectangle(cornerRadius: 5, style: .continuous)
                                        .stroke(.white.opacity(day.dailyTotal > 0 ? 0.18 : 0.03), lineWidth: hoveredDay?.id == day.id ? 1.2 : 0.6)
                                }
                                .opacity(day.isFuture ? 0 : 1)
                                .scaleEffect(hoveredDay?.id == day.id ? 1.16 : 1)
                                .onHover { isInside in
                                    if isInside && !day.isFuture {
                                        hoveredDay = day
                                        tooltipPosition = CGPoint(
                                            x: CGFloat(weekIndex) * (cellWidth + cellSpacing) + cellWidth / 2,
                                            y: CGFloat(dayIndex) * (cellHeight + cellSpacing)
                                        )
                                    } else if hoveredDay?.id == day.id {
                                        hoveredDay = nil
                                        tooltipPosition = nil
                                    }
                                }
                        }
                    }
                }
            }
            .frame(width: gridWidth, height: gridHeight, alignment: .topLeading)

            if let hoveredDay, let tooltipPosition {
                HeatmapTooltip(day: hoveredDay, mode: mode)
                    .fixedSize()
                    .position(
                        x: min(max(tooltipPosition.x, 94), gridWidth - 94),
                        y: max(-20, tooltipPosition.y - 18)
                    )
                    .transition(.scale(scale: 0.96).combined(with: .opacity))
                    .zIndex(10)
            }
        }
        .frame(width: gridWidth, height: gridHeight, alignment: .topLeading)
        .animation(.smooth(duration: 0.16), value: hoveredDay)
    }

    private var monthRangeText: String {
        let flat = weeks.flatMap { $0 }.filter { !$0.isFuture }
        guard let first = flat.first?.date, let last = flat.last?.date else { return "最近活动" }
        return "\(first.formatted(.dateTime.month())) - \(last.formatted(.dateTime.month()))"
    }

    private func color(for day: HeatmapDay) -> Color {
        guard day.value > 0 else { return .white.opacity(0.06) }
        let ratio = min(1, sqrt(Double(day.value) / Double(maxValue)))
        return Color.cyan.opacity(0.18 + ratio * 0.72)
    }

    private func makeHeatmapWeeks(mode: String) -> [[HeatmapDay]] {
        var calendar = Calendar.current
        calendar.firstWeekday = 2
        let end = calendar.startOfDay(for: summary.generatedAt)
        let rawStart = calendar.date(byAdding: .day, value: -167, to: end) ?? end
        let weekday = calendar.component(.weekday, from: rawStart)
        let daysFromMonday = (weekday + 5) % 7
        let start = calendar.date(byAdding: .day, value: -daysFromMonday, to: rawStart) ?? rawStart
        let details = Dictionary(uniqueKeysWithValues: summary.dailyUsageDetails(calendar: calendar).map { ($0.date, $0) })

        var days: [HeatmapDay] = []
        var cumulative = 0
        var cursor = start
        while cursor <= (calendar.date(byAdding: .day, value: 6, to: end) ?? end) {
            let detail = details[calendar.startOfDay(for: cursor)]
            let dailyTotal = detail?.totalTokens ?? 0
            cumulative += cursor <= end ? dailyTotal : 0
            let value: Int
            switch mode {
            case "每周":
                value = weeklyTotal(for: cursor, details: details, calendar: calendar)
            case "累计":
                value = cumulative
            default:
                value = dailyTotal
            }
            days.append(HeatmapDay(date: cursor, value: value, dailyTotal: dailyTotal, isFuture: cursor > end))
            guard let next = calendar.date(byAdding: .day, value: 1, to: cursor) else { break }
            cursor = next
        }

        return stride(from: 0, to: days.count, by: 7).map { startIndex in
            Array(days[startIndex..<min(startIndex + 7, days.count)])
        }
    }

    private func weeklyTotal(
        for date: Date,
        details: [Date: DailyUsageDetail],
        calendar: Calendar
    ) -> Int {
        guard let interval = calendar.dateInterval(of: .weekOfYear, for: date) else { return 0 }
        return details.values.reduce(0) { total, detail in
            interval.contains(detail.date) ? total + detail.totalTokens : total
        }
    }
}

private struct HeatmapDay: Identifiable, Hashable {
    var id: Date { date }
    let date: Date
    let value: Int
    let dailyTotal: Int
    let isFuture: Bool
}

private struct HeatmapTooltip: View {
    let day: HeatmapDay
    let mode: String

    var body: some View {
        HStack(spacing: 8) {
            Text(day.date.formatted(.dateTime.month().day()))
                .fontWeight(.bold)
            Text(tooltipText)
        }
        .font(.system(size: 15, weight: .semibold, design: .rounded))
        .foregroundStyle(.white)
        .monospacedDigit()
        .padding(.horizontal, 14)
        .frame(height: 38)
        .background {
            RoundedRectangle(cornerRadius: 12, style: .continuous)
                .fill(Color(red: 0.13, green: 0.13, blue: 0.14).opacity(0.96))
                .overlay {
                    RoundedRectangle(cornerRadius: 12, style: .continuous)
                        .stroke(.white.opacity(0.16), lineWidth: 1)
                }
                .shadow(color: .black.opacity(0.32), radius: 16, y: 10)
        }
    }

    private var tooltipText: String {
        switch mode {
        case "每周":
            return "所在周使用了 \(TokenFormatter.format(day.value)) 个 Token"
        case "累计":
            return "累计使用了 \(TokenFormatter.format(day.value)) 个 Token"
        default:
            return "使用了 \(TokenFormatter.format(day.dailyTotal)) 个 Token"
        }
    }
}

private struct HeatmapLegend: View {
    let color: (Int) -> Color

    var body: some View {
        HStack(spacing: 5) {
            Text("少")
                .font(.system(size: 11, weight: .semibold))
                .foregroundStyle(.secondary)
            ForEach([0, 1, 2, 3], id: \.self) { index in
                RoundedRectangle(cornerRadius: 3, style: .continuous)
                    .fill(color(index + 1))
                    .frame(width: 10, height: 10)
            }
            Text("多")
                .font(.system(size: 11, weight: .semibold))
                .foregroundStyle(.secondary)
        }
    }
}

private struct HeatmapStat: View {
    let title: String
    let value: String

    var body: some View {
        VStack(alignment: .leading, spacing: 2) {
            Text(title)
                .font(.system(size: 10, weight: .bold))
                .foregroundStyle(.secondary)
            Text(value)
                .font(.system(size: 13, weight: .bold, design: .rounded))
                .monospacedDigit()
        }
        .padding(.horizontal, 10)
        .frame(maxWidth: .infinity, minHeight: 38, alignment: .leading)
        .background(.white.opacity(0.06), in: RoundedRectangle(cornerRadius: 12, style: .continuous))
        .overlay(RoundedRectangle(cornerRadius: 12).stroke(.white.opacity(0.08)))
    }
}

struct InsightsPanel: View {
    let insights: [Insight]

    var body: some View {
        GlassCard {
            VStack(spacing: 12) {
                HStack {
                    Text("洞察提醒")
                        .font(.system(size: 21, weight: .bold, design: .rounded))
                    Spacer()
                    Text("查看全部")
                        .font(.system(size: 14, weight: .semibold))
                        .foregroundStyle(.blue)
                }
                ForEach(insights) { insight in
                    HStack(alignment: .top, spacing: 12) {
                        RoundedRectangle(cornerRadius: 10)
                            .fill(insight.tone.color.opacity(0.2))
                            .frame(width: 36, height: 36)
                            .overlay {
                                Image(systemName: insight.tone.symbol)
                                    .font(.system(size: 17, weight: .bold))
                                    .foregroundStyle(insight.tone.color)
                            }
                        VStack(alignment: .leading, spacing: 4) {
                            Text(insight.title)
                                .font(.system(size: 15, weight: .bold))
                            Text(insight.message)
                                .font(.system(size: 13))
                                .foregroundStyle(.secondary)
                        }
                        Spacer()
                    }
                    .padding(12)
                    .background(insight.tone.color.opacity(0.08), in: RoundedRectangle(cornerRadius: 16))
                    .overlay(RoundedRectangle(cornerRadius: 16).stroke(insight.tone.color.opacity(0.2)))
                }
            }
        }
    }
}

struct AmbientBackground: View {
    var body: some View {
        ZStack {
            LinearGradient(colors: [Color(red: 0.03, green: 0.06, blue: 0.11), Color(red: 0.04, green: 0.09, blue: 0.15)], startPoint: .topLeading, endPoint: .bottomTrailing)
            Circle()
                .fill(.blue.opacity(0.16))
                .frame(width: 520, height: 520)
                .blur(radius: 90)
                .offset(x: -380, y: -260)
            Circle()
                .fill(.cyan.opacity(0.12))
                .frame(width: 430, height: 430)
                .blur(radius: 80)
                .offset(x: 420, y: -210)
            Circle()
                .fill(.purple.opacity(0.14))
                .frame(width: 520, height: 520)
                .blur(radius: 110)
                .offset(x: 280, y: 350)
        }
        .ignoresSafeArea()
    }
}

extension Provider {
    var color: Color {
        switch self {
        case .claude: .blue
        case .codex: .purple
        case .gemini: .cyan
        case .hermes: .green
        case .opencode: .orange
        }
    }
}

extension Insight.Tone {
    var color: Color {
        switch self {
        case .warning: .orange
        case .positive: .green
        case .accent: .purple
        }
    }

    var symbol: String {
        switch self {
        case .warning: "exclamationmark"
        case .positive: "checkmark"
        case .accent: "arrow.up.right"
        }
    }
}
