import APIClient
import ComponentLibrary
import SwiftUI

public struct ShortcutCard: View {
    let shortcut: Shortcut
    let onTap: () -> Void

    @State var isPressed = false

    private struct ImageLayer {
        let rotation: Double
        var animation: Double = 1.3
        let opacity: Double
        let blur: Bool
        let showOverlay: Bool
    }

    @State private var imageLayers: [ImageLayer]

    public init(
        shortcut: Shortcut,
        onTap: @escaping () -> Void
    ) {
        self.shortcut = shortcut
        self.onTap = onTap

        let order = Double(Bool.random() ? -1 : 1)
        self.imageLayers = [
            ImageLayer(rotation: .random(in: -8 ... -6) * order, opacity: 0.25, blur: true, showOverlay: false),
            ImageLayer(rotation: .random(in: 6 ... 8) * order, opacity: 0.45, blur: true, showOverlay: false),
            ImageLayer(rotation: .random(in: -1 ... 1), animation: 1.1, opacity: 1.0, blur: false, showOverlay: true),
        ]
    }

    public var body: some View {
        Button(action: onTap) {
            AsyncImage(url: URL(string: shortcut.imageUrl)) { phase in
                switch phase {
                case .empty:
                    Placeholder()
                case .success(let image):
                    imageLayersView(image: image)
                case .failure:
                    imageLayersView(image: defaultImage(for: shortcut.id))
                @unknown default:
                    imageLayersView(image: defaultImage(for: shortcut.id))
                }
            }
            .animation(.smooth(duration: 0.25), value: isPressed)
        }
        .buttonStyle(ScaleButtonStyle(scaleAmount: 0.935, isPressed: $isPressed))
    }

    private func imageLayersView(image: Image) -> some View {
        ZStack {
            ForEach(0 ..< imageLayers.count, id: \.self) { index in
                imageLayer(
                    image: image,
                    rotation: imageLayers[index].rotation,
                    animation: imageLayers[index].animation,
                    opacity: imageLayers[index].opacity,
                    blur: imageLayers[index].blur,
                    showOverlay: imageLayers[index].showOverlay
                )
            }
        }
        .frame(width: 165, height: 165)
        .overlay(alignment: .bottomLeading) {
            shortcutTitleAndDescription
        }
    }

    private func imageLayer(
        image: Image,
        rotation: Double,
        animation: Double,
        opacity: Double,
        blur: Bool,
        showOverlay: Bool
    ) -> some View {
        image
            .resizable()
            .aspectRatio(contentMode: .fill)
            .frame(width: 150, height: 150)
            .blur(radius: blur ? 12 : 0)
            .scaleEffect(blur ? 1.15 : 1.0)
            .overlay(
                showOverlay ? overlayGradient.clipShape(RoundedRectangle(cornerRadius: 12)) : nil
            )
            .background(.ultraThinMaterial)
            .glassBorder(shape: .rect(cornerRadius: 16))
            .clipShape(RoundedRectangle(cornerRadius: 16))
            .rotationEffect(.degrees(rotation * (isPressed ? animation : 1)))
            .opacity(opacity)
            .saturation(opacity)
    }

    private var overlayGradient: some View {
        LinearGradient(
            stops: [
                Gradient.Stop(color: .black.opacity(0), location: 0),
                Gradient.Stop(color: .black.opacity(0.6), location: 1),
            ],
            startPoint: UnitPoint(x: 0.5, y: 0),
            endPoint: UnitPoint(x: 0.5, y: 1)
        )
    }

    private var shortcutTitleAndDescription: some View {
        VStack(alignment: .leading, spacing: 0) {
            Spacer()
            Text(shortcut.name)
                .typographyV1(.shortcutTitle)
                .foregroundStyle(.white)
                .multilineTextAlignment(.leading)
                .lineLimit(2)
            if let description = shortcut.description, !description.isEmpty {
                Text(description)
                    .typographyV1(.shortcutDescription)
                    .foregroundStyle(.white)
                    .opacity(0.65)
                    .multilineTextAlignment(.leading)
                    .lineLimit(2)
            }
        }
        .padding(16)
    }
}

// MARK: - Typography Extensions

private extension TypographyV1 {
    static let shortcutTitle: TypographyV1 = .init(
        name: "Shortcut Title",
        size: 14,
        style: .body,
        weight: .ppNeueMontrealMedium,
        kerning: 0.28,
        lineHeight: 22
    )

    static let shortcutDescription: TypographyV1 = .init(
        name: "Shortcut Description",
        size: 12,
        style: .body,
        weight: .ppNeueMontrealRegular,
        kerning: 0.24,
        lineHeight: 18
    )
}

// MARK: - Placeholder

extension ShortcutCard {
    public struct Placeholder: View {
        private struct ImageLayer {
            let rotation: Double
            let opacity: Double
        }

        private let imageLayers: [ImageLayer]

        public init() {
            let order = Double(Bool.random() ? -1 : 1)
            self.imageLayers = [
                ImageLayer(rotation: .random(in: -8 ... -6) * order, opacity: 0.8),
                ImageLayer(rotation: .random(in: 6 ... 8) * order, opacity: 0.8),
                ImageLayer(rotation: .random(in: -1 ... 1), opacity: 1.0),
            ]
        }

        public var body: some View {
            ZStack {
                ForEach(0 ..< imageLayers.count, id: \.self) { index in
                    placeholderImageLayer(
                        rotation: imageLayers[index].rotation,
                        opacity: imageLayers[index].opacity
                    )
                }
            }
            .frame(width: 165, height: 165)
            .overlay(alignment: .bottomLeading) {
                placeholderTextLayer
            }
        }

        private func placeholderImageLayer(rotation: Double, opacity: Double) -> some View {
            RoundedRectangle(cornerRadius: 16)
                .fill(Color.SemanticV2.backgroundSecondary)
                .frame(width: 150, height: 150)
                .rotationEffect(.degrees(rotation))
                .opacity(opacity)
                .placeholderShimmering(isVisible: opacity == 1.0, cornerRadius: 16)
        }

        private var placeholderTextLayer: some View {
            VStack(alignment: .leading, spacing: 4) {
                RoundedRectangle(cornerRadius: 20)
                    .frame(width: 43, height: 14)
                    .foregroundColor(.white.opacity(0.1))
                RoundedRectangle(cornerRadius: 20)
                    .frame(width: 63, height: 14)
                    .foregroundColor(.white.opacity(0.1))
            }
            .padding(16)
        }
    }
}
