import SwiftUI

/// Buttons per `DESIGN (1).md` → Components → Buttons: "Solid #000000
/// background with #FFFFFF text for primary actions. 1px solid #000000
/// border with no fill for secondary. All buttons are rectangular [0px
/// radius] with no padding-inline under 24px." And → Elevation: "On hover,
/// elements do not lift; they shift color... a button fill turns from Black
/// to Slate Blue-Grey" — the pressed state here plays the role "hover" plays
/// on the web.
/// Every Zenith button style dims to this opacity when `.disabled(true)` —
/// centralised here so a disabled `.zenithPrimary` etc. dims automatically,
/// the way `.borderedProminent`/`.bordered` do out of the box. Without this,
/// each call site would need its own manual `.opacity(isEnabled ? 1 : 0.4)`,
/// which is easy to forget (an earlier pass of this app's screens did, in
/// fact, forget it in a couple of places before this was added centrally).
private let zenithDisabledOpacity: Double = 0.4

struct ZenithPrimaryButtonStyle: ButtonStyle {
    var isDestructive = false

    @Environment(\.isEnabled) private var isEnabled

    func makeBody(configuration: Configuration) -> some View {
        configuration.label
            .font(.zenithBodyMd)
            .fontWeight(.medium)
            .foregroundStyle(.white)
            .frame(maxWidth: .infinity, minHeight: 50)
            .padding(.horizontal, ZenithSpacing.md)
            .background(fill(pressed: configuration.isPressed))
            // Sharp corners are the point of this system — a plain
            // Rectangle fill, never `.cornerRadius`.
            .opacity(isEnabled ? 1 : zenithDisabledOpacity)
    }

    private func fill(pressed: Bool) -> Color {
        if isDestructive { return pressed ? Color.zenithError.opacity(0.8) : .zenithError }
        return pressed ? .zenithSlate : .zenithBlack
    }
}

struct ZenithSecondaryButtonStyle: ButtonStyle {
    var isDestructive = false

    @Environment(\.isEnabled) private var isEnabled

    func makeBody(configuration: Configuration) -> some View {
        configuration.label
            .font(.zenithBodyMd)
            .fontWeight(.medium)
            .foregroundStyle(isDestructive ? Color.zenithError : Color.zenithBlack)
            .frame(maxWidth: .infinity, minHeight: 50)
            .padding(.horizontal, ZenithSpacing.md)
            .background(Color.zenithSurface)
            .overlay(
                // Border THICKENS on press instead of the fill lifting —
                // same "no lift, shift instead" rule as the primary style.
                Rectangle()
                    .strokeBorder(
                        isDestructive ? Color.zenithError : Color.zenithBlack,
                        lineWidth: configuration.isPressed ? 2 : 1
                    )
            )
            .opacity(isEnabled ? 1 : zenithDisabledOpacity)
    }
}

/// A plain-text button with no fill/border at all — for tertiary actions
/// ("Noch kein Konto? Registrieren", "Abbrechen") that shouldn't compete
/// visually with a screen's primary/secondary buttons.
struct ZenithPlainButtonStyle: ButtonStyle {
    var color: Color = .zenithMuted

    @Environment(\.isEnabled) private var isEnabled

    func makeBody(configuration: Configuration) -> some View {
        configuration.label
            .font(.zenithBodySm)
            .foregroundStyle(configuration.isPressed ? color.opacity(0.6) : color)
            .opacity(isEnabled ? 1 : zenithDisabledOpacity)
    }
}

extension ButtonStyle where Self == ZenithPrimaryButtonStyle {
    static var zenithPrimary: ZenithPrimaryButtonStyle { ZenithPrimaryButtonStyle() }
    static var zenithPrimaryDestructive: ZenithPrimaryButtonStyle { ZenithPrimaryButtonStyle(isDestructive: true) }
}

extension ButtonStyle where Self == ZenithSecondaryButtonStyle {
    static var zenithSecondary: ZenithSecondaryButtonStyle { ZenithSecondaryButtonStyle() }
    static var zenithSecondaryDestructive: ZenithSecondaryButtonStyle { ZenithSecondaryButtonStyle(isDestructive: true) }
}

extension ButtonStyle where Self == ZenithPlainButtonStyle {
    static var zenithPlain: ZenithPlainButtonStyle { ZenithPlainButtonStyle() }
}
