import SwiftUI
import WireProtocol

/// # Status visuals — the SINGLE source (FROZEN public surface)
///
/// Every place that shows a session's Claude-Code status (list rows, badges,
/// thumbnails, project-detail rows, banners) resolves it through here, so the
/// color + shape + label stay identical everywhere. Status is expressed as
/// **color AND a distinct SF Symbol** — never color alone (accessibility;
/// color-blind users read the shape). Labels are Chinese for VoiceOver + UI.

/// The seven visual states a status indicator can show. A superset of the wire
/// `ClaudeStatus` (working/waiting/idle/unknown/stuck) plus two App-layer
/// emphasis states:
/// - `pendingApproval` — a tool/plan gate is held server-side ("needs me").
///   Outranks status; mirrors `SessionListViewModel.Indicator.pendingApproval`
///   (this type does NOT re-implement that priority — callers decide when to
///   use it; here it's only its visual identity).
/// - `exited` — the session is over (read-only).
enum DisplayStatus: CaseIterable, Sendable, Equatable {
    case working
    case waiting
    case idle
    case stuck
    case unknown
    case pendingApproval
    case exited

    /// Bridge from the wire enum. Pure — no pending/exited emphasis (callers
    /// supply those explicitly, matching the VM's own indicator priority).
    init(_ claude: ClaudeStatus) {
        switch claude {
        case .working: self = .working
        case .waiting: self = .waiting
        case .idle: self = .idle
        case .stuck: self = .stuck
        case .unknown: self = .unknown
        }
    }
}

/// Resolved visuals for one status: a semantic color, a DISTINCT SF Symbol
/// shape, and a Chinese label (used as the VoiceOver string too). The mapping
/// itself is pure — no UIKit, deterministic, unit-testable.
struct StatusStyle: Equatable, Sendable {
    /// Semantic color from `DS.Palette` (never the sole signal — see `symbolName`).
    let color: Color
    /// SF Symbol name. Distinct across all seven statuses so shape alone
    /// disambiguates (color-blind safe).
    let symbolName: String
    /// Chinese status word — shown as an optional label and always as the
    /// accessibility label.
    let label: String

    /// The frozen mapping. Each status → (color, distinct symbol, 中文 label).
    static func style(for status: DisplayStatus) -> StatusStyle {
        switch status {
        case .working:
            // solid filled circle — actively running
            return StatusStyle(color: DS.Palette.statusWorking, symbolName: "circle.fill", label: "运行中")
        case .waiting:
            // clock — waiting on something
            return StatusStyle(color: DS.Palette.statusWaiting, symbolName: "clock.fill", label: "等待中")
        case .idle:
            // hollow circle — quiet/empty (gray, distinct from working's fill)
            return StatusStyle(color: DS.Palette.statusIdle, symbolName: "circle", label: "空闲")
        case .stuck:
            // triangle — alarm
            return StatusStyle(color: DS.Palette.statusStuck, symbolName: "exclamationmark.triangle.fill", label: "卡住")
        case .unknown:
            // question mark — no signal yet
            return StatusStyle(color: DS.Palette.statusUnknown, symbolName: "questionmark.circle", label: "未知")
        case .pendingApproval:
            // filled ! circle — "needs me", the single most important prompt
            return StatusStyle(color: DS.Palette.statusWaiting, symbolName: "exclamationmark.circle.fill", label: "等待审批")
        case .exited:
            // checkered flag — session over (mirrors ReconnectBanner's exited icon)
            return StatusStyle(color: DS.Palette.statusExited, symbolName: "flag.checkered", label: "已退出")
        }
    }

    /// Convenience bridge from the wire enum.
    static func style(for claude: ClaudeStatus) -> StatusStyle {
        style(for: DisplayStatus(claude))
    }
}
