//
//  Callout.swift
//  ThemeKit
//  Created by İsa Mercan on 23.06.2026.
//

import SwiftUI

public enum CalloutType {
    case neutral, info, success, warning, error

    func accent(_ theme: Theme) -> Color {
        switch self {
        case .neutral: return theme.text(.textSecondary)
        case .info: return theme.foreground(.systemcolorsFgInfo)
        case .success: return theme.foreground(.systemcolorsFgSuccess)
        case .warning: return theme.foreground(.systemcolorsFgWarning)
        case .error: return theme.foreground(.systemcolorsFgError)
        }
    }
    func soft(_ theme: Theme) -> Color {
        switch self {
        case .neutral: return theme.background(.bgElevatorPrimary)
        case .info: return theme.background(.systemcolorsBgInfoLight)
        case .success: return theme.background(.systemcolorsBgSuccessLight)
        case .warning: return theme.background(.systemcolorsBgWarningLight)
        case .error: return theme.background(.systemcolorsBgErrorLight)
        }
    }
    var systemImage: String {
        switch self {
        case .neutral, .info: return "info.circle"
        case .success: return "checkmark.circle"
        case .warning: return "exclamationmark.triangle"
        case .error: return "exclamationmark.circle"
        }
    }
}

public enum CalloutStyle {
    case plain   // transparent, colored icon + text
    case soft    // light tinted surface
}

/// Organism. Inline status text with a leading icon. More compact than
/// InfoBanner — used to highlight a single line of information.
/// Figma: success / error / info / warning / neutral; plain or soft style.
public struct Callout: View {
    @Environment(\.theme) private var theme

    // Appearance/content/state — mutated only through the modifiers below (R2).
    private var type: CalloutType = .info
    private var style: CalloutStyle = .plain
    private var showIcon = true
    private var actionTitle: String?
    private var onAction: (() -> Void)?
    private var onClose: (() -> Void)?

    private let text: String

    public init(_ text: String) {   // R1
        self.text = text
    }

    private var hasAction: Bool { actionTitle != nil && onAction != nil }
    private var hasTrailing: Bool { hasAction || onClose != nil }

    public var body: some View {
        HStack(alignment: .firstTextBaseline, spacing: Theme.SpacingKey.xs.value) {
            if showIcon {
                Image(systemName: type.systemImage)
                    .font(.system(size: 14))
            }
            Text(text)
                .textStyle(.bodySm400)
            if hasTrailing {
                Spacer(minLength: Theme.SpacingKey.sm.value)
                if let actionTitle, let onAction {
                    Button(action: onAction) {
                        Text(actionTitle).textStyle(.labelSm600)
                    }
                    .buttonStyle(.plain)
                }
                if let onClose {
                    Button(action: onClose) {
                        Image(systemName: "xmark").font(.system(size: 11, weight: .semibold))
                    }
                    .buttonStyle(.plain)
                    .accessibilityLabel(String(themeKit: "Dismiss"))
                }
            }
        }
        .foregroundStyle(type.accent(theme))
        .padding(.horizontal, style == .soft ? Theme.SpacingKey.sm.value : 0)
        .padding(.vertical, style == .soft ? Theme.SpacingKey.xs.value : 0)
        .background {
            if style == .soft {
                RoundedRectangle(cornerRadius: Theme.RadiusKey.xs.value, style: .continuous).fill(type.soft(theme))
            }
        }
    }
}

// MARK: - Modifiers (R2 copy-on-write · R5 standard vocabulary)

public extension Callout {
    /// Semantic status: neutral / info / success / warning / error (drives accent + icon).
    func variant(_ t: CalloutType) -> Self { copy { $0.type = t } }

    /// Surface treatment: plain (transparent) or soft (light tinted surface).
    func calloutStyle(_ s: CalloutStyle) -> Self { copy { $0.style = s } }

    /// Show or hide the leading status icon.
    func showsIcon(_ on: Bool = true) -> Self { copy { $0.showIcon = on } }

    /// Trailing inline action button (title + handler).
    func action(_ title: String, onAction: @escaping () -> Void) -> Self {
        copy { $0.actionTitle = title; $0.onAction = onAction }
    }

    /// Trailing dismiss (×) button handler.
    func onClose(_ action: (() -> Void)?) -> Self { copy { $0.onClose = action } }

    private func copy(_ mutate: (inout Self) -> Void) -> Self {   // R2 — single mutation point
        var c = self
        mutate(&c)
        return c
    }
}

#Preview {
    VStack(alignment: .leading, spacing: 10) {
        Callout("Lorem ipsum placeholder text.").variant(.success)
        Callout("Lorem ipsum placeholder text.").variant(.error)
        Callout("Lorem ipsum placeholder text.").variant(.info)
        Callout("Lorem ipsum placeholder text.").variant(.warning).calloutStyle(.soft)
        Callout("Lorem ipsum placeholder text.").variant(.neutral).calloutStyle(.soft)
    }
    .padding()
}
