//
// GoalTrackCard.swift
// Workouts
//
// Copyright 2026 Rouslan Zenetl. All Rights Reserved.
//

import SwiftUI

/// One goal's adherence card: a 12-week strip (each square filled by that week's
/// met/expected fraction), the weekly streak flame, and a this-week dot row per
/// member schedule. The goal is the ledger category — this track continues unbroken
/// across schedule rewrites.
struct GoalTrackCard: View {
    let track: GoalTrack

    private var color: Color {
        track.goal.map { Color.color(from: $0.colorName) } ?? Color(.systemGray)
    }

    var body: some View {
        VStack(alignment: .leading, spacing: 12) {
            HStack {
                Label(track.goal?.displayName ?? "Unassigned",
                      systemImage: track.goal?.systemImage ?? "tag")
                    .font(.headline)
                    .foregroundStyle(color)
                Spacer()
                if track.streakWeeks > 0 {
                    streakBadge
                }
            }

            weekStrip

            VStack(alignment: .leading, spacing: 10) {
                ForEach(track.scheduleTracks, id: \.schedule.id) { scheduleTrack in
                    scheduleRow(scheduleTrack)
                }
            }
        }
        .progressCard()
    }

    /// The streak flame: orange while the current week is still meetable, dimmed the
    /// moment it can no longer be (the streak is at stake, not yet erased).
    private var streakBadge: some View {
        HStack(spacing: 3) {
            Image(systemName: "flame.fill")
            Text("\(track.streakWeeks) wk")
                .monospacedDigit()
        }
        .font(.subheadline.weight(.semibold))
        .foregroundStyle(track.streakAlive ? Color.orange : Color.secondary)
        .accessibilityLabel("\(track.streakWeeks)-week streak\(track.streakAlive ? "" : ", at risk")")
    }

    private var weekStrip: some View {
        HStack(spacing: 4) {
            ForEach(Array(track.weeks.enumerated()), id: \.offset) { index, week in
                RoundedRectangle(cornerRadius: 3, style: .continuous)
                    .fill(fill(for: week))
                    .frame(height: 16)
                    .overlay {
                        // Outline the in-flight week so "unfilled" reads as "not over
                        // yet" rather than "missed".
                        if index == track.weeks.count - 1 {
                            RoundedRectangle(cornerRadius: 3, style: .continuous)
                                .strokeBorder(color.opacity(0.8), lineWidth: 1.5)
                        }
                    }
            }
        }
        .accessibilityElement(children: .ignore)
        .accessibilityLabel(stripSummary)
    }

    private func fill(for week: WeekMark) -> Color {
        if week.isVacuous { return Color(.systemFill).opacity(0.4) }
        if week.fraction == 0 { return Color(.systemFill) }
        return color.opacity(0.25 + 0.75 * week.fraction)
    }

    private var stripSummary: String {
        let hit = track.weeks.filter { !$0.isVacuous && $0.hit }.count
        let active = track.weeks.filter { !$0.isVacuous }.count
        return "Hit \(hit) of the last \(active) weeks"
    }

    private func scheduleRow(_ scheduleTrack: ScheduleTrack) -> some View {
        let schedule = scheduleTrack.schedule
        return HStack(alignment: .firstTextBaseline) {
            VStack(alignment: .leading, spacing: 2) {
                Text(schedule.routineName)
                    .font(.subheadline)
                Text(schedule.recurrence.summary(
                    weekdays: schedule.weekdays,
                    date: schedule.onceDate))
                    .font(.caption)
                    .foregroundStyle(.secondary)
            }
            Spacer()
            thisWeekDots(scheduleTrack)
        }
    }

    /// This week for one schedule: `expected` dots, `met` of them filled. A broken
    /// week adds a quiet "missed" tag — informative, not scolding.
    @ViewBuilder
    private func thisWeekDots(_ scheduleTrack: ScheduleTrack) -> some View {
        if let week = scheduleTrack.currentWeek, !week.isVacuous {
            HStack(spacing: 5) {
                if scheduleTrack.currentWeekBroken {
                    Text("missed")
                        .font(.caption2)
                        .foregroundStyle(.secondary)
                }
                ForEach(0..<week.expected, id: \.self) { index in
                    Circle()
                        .fill(index < week.met ? color : Color.clear)
                        .overlay {
                            if index >= week.met {
                                Circle().strokeBorder(color.opacity(0.4), lineWidth: 1.5)
                            }
                        }
                        .frame(width: 9, height: 9)
                }
            }
            .accessibilityElement(children: .ignore)
            .accessibilityLabel("\(week.met) of \(week.expected) this week")
        } else {
            Text("—")
                .font(.caption)
                .foregroundStyle(.tertiary)
        }
    }
}
