import Adamantium
import APIClient
import ComponentLibrary
import SwiftUI

public struct StyleCard: View {
    private let style: StyleItem

    var textAlignment: Alignment {
        switch style.auraSettings?.textPlacement {
        case .topLeft: return .topLeading
        case .middle: return .center
        case .bottomRight: return .bottomTrailing
        case nil: return .topLeading
        }
    }

    @State private var maskedAuraImage: UIImage?
    @State private var standardAuraImage: UIImage?

    public init(style: StyleItem) {
        self.style = style
    }

    public var body: some View {
        Group {
            if let settings = style.auraSettings {
                switch settings.frameShape {
                case .square:
                    square(settings)
                case .round:
                    round
                }
            } else {
                noAura
            }
        }
        .onAppear {
            #if targetEnvironment(simulator)
                standardAuraImage = defaultImage(for: style.id)
            #else
                if let auraSettings = style.auraSettings {
                    let size = 400
                    let colorSet: SunoTriColorSet = {
                        switch auraSettings.colorSet {
                        case .redVioletBlue: return .redLVioletBlue
                        case .tanLaserBluePink: return .tanLaserBluePink
                        case .cherryYellowMoss: return .cherryYellowMoss
                        case .goldMossPink: return .goldMossPink
                        case .orangeMauveLime: return .orangeMauveLime
                        case .yellowOrangeBlue: return .yellowOrangeBlue
                        case .mauveVioletGreen: return .mauveVioletGreen
                        case .fadedBlueGoldSand: return .fadedBlueGoldSand
                        case .maroonVioletRed: return .maroonVioletRed
                        case .indigoBlueYellow: return .custom(.discoGold, .playgroundSand, .electricBlue)
                        case .purpleOrangePurple: return .custom(.vacationViolet, .sunsetOrange, .mixtapeMauve)
                        }
                    }()

                    // Aura style (right arrow, bottom ripple, ...)
                    if auraSettings.style == .null {
                        if let auraStillCGImage = try? AuraStillRender.renderStandardAuraToStill(
                            .init(
                                width: size,
                                height: size,
                                colorSet: colorSet,
                                scale: 1.5,
                                seed: Float.random(in: 0.0 ... 1000.0)
                            )
                        ) {
                            standardAuraImage = .init(cgImage: auraStillCGImage)
                        }
                    } else {
                        let auraStillRenderer = MaskedAuraStillRender()
                        let auraRenderConfig = MaskedAuraStillRender.RenderConfig(
                            width: size,
                            height: size,
                            colorSet: colorSet,
                            overlayColor: {
                                switch auraSettings.overlayColor {
                                case .null: return .custom(0, 0, 0)
                                case .yellow1: return .popcornYellow
                                case .yellow2: return .discoGold
                                case .yellow3: return .playgroundSand
                                case .orange1: return .sunsetOrange
                                case .orange2: return .rubikRed
                                case .orange3: return .californiaTan
                                case .pink1: return .bubblegumPink
                                case .pink2: return .vintageCherry
                                case .pink3: return .arcadeMaroon
                                case .purple1: return .vacationViolet
                                case .purple2: return .lavaLavender
                                case .purple3: return .mixtapeMauve
                                case .blue1: return .fadedBlue
                                case .blue2: return .laserBlue
                                case .blue3: return .electricBlue
                                case .green1: return .wallpaperGreen
                                case .green2: return .neonLime
                                case .green3: return .cadillacMoss
                                }
                            }(),
                            maskingType: {
                                switch auraSettings.maskStyle {
                                case .full, .floatingImage: return .noMask
                                case .topLeft: return .topLeft
                                case .bottomRight: return .bottomRight
                                }
                            }(),
                            auraShape: {
                                switch auraSettings.style {
                                case .null: return .standard
                                case .cornerRipple: return .cornerRipple
                                case .rightArrow: return .rightArrow
                                case .bottomRipple: return .bottomRipple
                                case .curveEcho: return .curveEcho
                                case .circleTile: return .circleTile
                                case .diamond: return .diamond
                                case .sunburst: return .sunburst
                                case .circleGlass: return .circleGlass
                                case .circleFlower: return .circleFlower
                                case .stars: return .star
                                case .circleRipple: return .circleRipple
                                case .curveRotation: return .curveRotation
                                case .circle: return .circle
                                case .waves: return .waves
                                case .gradientDown: return .gradientDown
                                }
                            }(),
                            auraShapeMapOffsetScalar: 2.000,
                            scale: 2.000,
                            seed: 0.000
                        )

                        let mtlTexture = auraStillRenderer.render(auraRenderConfig)
                        if let maskedAuraCgImage = try? StillCaptureUtility.cgImage(texture: mtlTexture) {
                            maskedAuraImage = .init(cgImage: maskedAuraCgImage)
                        }
                    }
                }
            #endif
        }
    }

    // MARK: - Square

    @ViewBuilder
    private func square(_ settings: AuraSettings) -> some View {
        switch settings.maskStyle {
        case .topLeft:
            masked(alignment: .bottomTrailing)
        case .bottomRight:
            masked(alignment: .topLeading)
        case .full:
            full
        case .floatingImage:
            floatingImage
        }
    }

    // Default card, no aura
    private var noAura: some View {
        RemoteImage(url: style.imageUrl, fallbackId: style.id)
            .aspectRatio(contentMode: .fill)
            .clipShape(.rect(cornerRadius: 12))
            .overlay {
                Text(style.name)
                    .typographyV1(.styleCardTitle)
                    .lineLimit(1)
                    .minimumScaleFactor(0.6)
                    .foregroundColor(.SemanticV1.textPrimary)
                    .padding(.horizontal, 8)
                    .padding(.vertical, 4)
                    .glassBackground(shape: .rect(cornerRadius: 8), type: nil, fallbackStyle: Material.ultraThin)
                    .padding(16)
            }
            .glassBorder(shape: .rect(cornerRadius: 12))
    }

    // Masked top leading / bottom trailing
    private func masked(alignment: Alignment) -> some View {
        ZStack {
            aura

            RemoteImage(url: style.imageUrl, fallbackId: style.id)
                .aspectRatio(contentMode: .fill)
                .mask(alignment: alignment) {
                    ZStack(alignment: alignment) {
                        Circle()
                            .frame(width: 140, height: 140)
                        Rectangle()
                            .frame(width: 140, height: 80)
                        Rectangle()
                            .frame(width: 80, height: 140)
                        Rectangle()
                            .frame(width: 20, height: 140)
                        Rectangle()
                            .frame(width: 140, height: 20)
                    }
                    .blur(radius: 14)
                }
        }
        .clipShape(.rect(cornerRadius: 12))
        .overlay(alignment: textAlignment) {
            Text(style.name)
                .typographyV1(.styleCardTitle)
                .foregroundColor(.SemanticV1.textPrimary)
                .padding(16)
                .environment(\.colorScheme, .dark)
        }
    }

    // Full aura no image
    private var full: some View {
        aura
            .clipShape(.rect(cornerRadius: 12))
            .overlay(alignment: textAlignment) {
                Text(style.name)
                    .typographyV1(.styleCardTitle)
                    .foregroundColor(.SemanticV1.textPrimary)
                    .multilineTextAlignment(.center)
                    .padding(16)
                    .environment(\.colorScheme, .dark)
            }
    }

    // Aura background with transparent image on bottom trailing
    private var floatingImage: some View {
        ZStack(alignment: .bottomTrailing) {
            aura

            // Image must be transparent in order to match designs
            RemoteImage(url: style.imageUrl, fallbackId: style.id)
                .aspectRatio(contentMode: .fit)
                .frame(width: 140, height: 110, alignment: .bottomTrailing)
                .clipped()
        }
        .clipShape(.rect(cornerRadius: 12))
        .overlay(alignment: textAlignment) {
            Text(style.name)
                .typographyV1(.styleCardTitle)
                .foregroundColor(.SemanticV1.textPrimary)
                .padding(16)
                .environment(\.colorScheme, .dark)
        }
    }

    // MARK: - Round

    private var round: some View {
        aura
            .clipShape(.circle)
            .overlay {
                Text(style.name)
                    .typographyV1(.styleCardTitle)
                    .foregroundColor(.SemanticV1.textPrimary)
                    .multilineTextAlignment(.center)
                    .padding(16)
                    .environment(\.colorScheme, .dark)
            }
    }

    // MARK: - Aura

    private var aura: some View {
        if let maskedAuraImage = maskedAuraImage {
            Image(uiImage: maskedAuraImage)
                .resizable()
                .aspectRatio(contentMode: .fill)
        } else if let standardAuraImage = standardAuraImage {
            Image(uiImage: standardAuraImage)
                .resizable()
                .aspectRatio(contentMode: .fill)
        } else {
            Image(uiImage: defaultImage(for: style.id))
                .resizable()
                .aspectRatio(contentMode: .fill)
        }
    }
}

private extension TypographyV1 {
    static let styleCardTitle: TypographyV1 = .init(
        name: "Style Card Title",
        size: 28,
        style: .title,
        weight: .editorialNewLight
    )
}
