import APIClient
import Localization
import SwiftUI

public struct VersioningPillV2: View {
    @Environment(\.colorScheme) var colorScheme

    public enum DisplayState: Equatable {
        case loading
        case v3_5
        case v4
        case v4_5
        case v4_5Plus
        case v5
        case modelBadge(style: ModelBadgeStyle)
    }

    let state: DisplayState
    let action: () -> Void
    let upgradeUpsellTarget: DisplayState?

    public init(
        state: DisplayState,
        upgradeUpsellTarget: DisplayState? = nil,
        action: @escaping () -> Void = {}
    ) {
        self.state = state
        self.action = action
        self.upgradeUpsellTarget = upgradeUpsellTarget
    }

    public var body: some View {
        ZStack {
            switch state {
            case .loading:
                Color.clear
                    .overlay {
                        ProgressView()
                            .progressViewStyle(.circular)
                    }

            case .v3_5, .v4, .v4_5, .v4_5Plus, .v5, .modelBadge:
                Button {
                    action()
                } label: {
                    HStack {
                        Text(primaryPillText)
                            .typographyV1(.caption4.neueMontrealRegular())
                            .padding(.horizontal, horizontalPadding)
                            .padding(.vertical, verticalPadding)
                            .foregroundColor(textColor)
                            .background(pillBackgroundView)
                    }
                }
                .buttonStyle(.plain)
            }
        }
    }
}

private extension VersioningPillV2 {
    enum Constants {
        static let regularHorizontalPadding: CGFloat = 8.0
        static let smallHorizontalPadding: CGFloat = 4.0
        static let verticalPaddingForVersionLabel: CGFloat = 1.0
        static let verticalPaddingForUpgradeUpsell: CGFloat = 2.5
        static let pillCornerRadius: CGFloat = 4.0
        static let pillLineWidth: CGFloat = 1.0
        static let v4Copy: String = "v4"
        static let v3Dot5Copy: String = "v3.5"
        static let v4Dot5Copy: String = "v4.5"
        static let v4Dot5PlusCopy: String = "v4.5+"
        static let v5Copy: String = "v5"
        static let pinkAccentColor: Color = Color.PaletteV2.pink600
        static var upgradeToV4Dot5Copy: String {
            return "\(L10n.FeatureBrandedAlert.upgradeTo(v4Dot5Copy))"
        }

        static var upgradeToV5Copy: String {
            return "\(L10n.FeatureBrandedAlert.upgradeTo(v5Copy))"
        }
    }

    var textColor: Color {
        switch state {
        case .loading:
            return Color.clear

        case .v3_5:
            if upgradeUpsellTarget != nil {
                return Constants.pinkAccentColor
            } else {
                return Color.clear
            }

        case .v4:
            return Color.SemanticV2.foregroundTertiary

        case .v4_5, .v4_5Plus, .v5:
            return Constants.pinkAccentColor

        case .modelBadge(let style):
            let colorStyle = colorScheme == .light ? style.light : style.dark
            return Color(hex: colorStyle.textColor)
        }
    }

    @ViewBuilder
    var pillBackgroundView: some View {
        switch state {
        case .loading:
            Color.clear

        case .v3_5:
            if upgradeUpsellTarget != nil {
                capsuleStrokeBackground
            } else {
                Color.clear
            }

        case .v4:
            if upgradeUpsellTarget != nil {
                capsuleStrokeBackground
            } else {
                roundedRectangleBackground()
            }

        case .v4_5, .v4_5Plus, .v5:
            capsuleStrokeBackground

        case .modelBadge(let style):
            let colorStyle = colorScheme == .light ? style.light : style.dark
            roundedRectangleBackground(
                fillColor: Color(hex: colorStyle.backgroundColor),
                borderColor: Color(hex: colorStyle.borderColor)
            )
        }
    }

    var backgroundColor: Color {
        switch state {
        case .loading:
            return Color.clear
        case .v3_5:
            return Color.clear
        case .v4:
            return Color.SemanticV2.backgroundSecondary
        case .v4_5, .v4_5Plus, .v5:
            return Color.clear
        case .modelBadge(let style):
            let colorStyle = colorScheme == .light ? style.light : style.dark
            return Color(hex: colorStyle.backgroundColor)
        }
    }

    var strokeColor: Color {
        switch state {
        case .loading:
            return Color.clear

        case .v3_5:
            if upgradeUpsellTarget != nil {
                return Constants.pinkAccentColor
            } else {
                return Color.clear
            }

        case .v4:
            if upgradeUpsellTarget != nil {
                return Constants.pinkAccentColor
            } else {
                return Color.SemanticV2.backgroundTertiary
            }

        case .v4_5, .v4_5Plus, .v5:
            return Constants.pinkAccentColor

        case .modelBadge(let style):
            let colorStyle = colorScheme == .light ? style.light : style.dark
            return Color(hex: colorStyle.borderColor)
        }
    }

    var primaryPillText: String {
        switch state {
        case .loading:
            return ""

        case .v3_5:
            if upgradeUpsellTarget != nil {
                return upgradeUpsellTarget == .v5 ? Constants.upgradeToV5Copy : Constants.upgradeToV4Dot5Copy
            } else {
                return Constants.v3Dot5Copy
            }

        case .v4:
            if upgradeUpsellTarget != nil {
                return upgradeUpsellTarget == .v5 ? Constants.upgradeToV5Copy : Constants.upgradeToV4Dot5Copy
            } else {
                return Constants.v4Copy
            }

        case .v4_5:
            return Constants.v4Dot5Copy

        case .v4_5Plus:
            return Constants.v4Dot5PlusCopy

        case .v5:
            return Constants.v5Copy

        case .modelBadge(let style):
            return style.displayName
        }
    }

    var verticalPadding: CGFloat {
        guard upgradeUpsellTarget != nil else {
            return Constants.verticalPaddingForVersionLabel
        }
        return Constants.verticalPaddingForUpgradeUpsell
    }

    var horizontalPadding: CGFloat {
        switch state {
        case .v4 where upgradeUpsellTarget == nil:
            return Constants.smallHorizontalPadding
        case .modelBadge:
            return Constants.regularHorizontalPadding
        default:
            return Constants.regularHorizontalPadding
        }
    }

    @ViewBuilder
    func roundedRectangleBackground(fillColor: Color? = nil, borderColor: Color? = nil) -> some View {
        ZStack {
            RoundedRectangle(cornerRadius: Constants.pillCornerRadius)
                .foregroundStyle(fillColor ?? backgroundColor)
            RoundedRectangle(cornerRadius: Constants.pillCornerRadius)
                .strokeBorder(borderColor ?? strokeColor, lineWidth: Constants.pillLineWidth, antialiased: true)
        }
    }

    @ViewBuilder
    var capsuleStrokeBackground: some View {
        ZStack {
            Capsule()
                .foregroundStyle(backgroundColor)
            Capsule()
                .strokeBorder(strokeColor, lineWidth: Constants.pillLineWidth, antialiased: true)
        }
    }
}
