//
//  CardView.swift
//  CasinoKit
//
//  Beautiful playing card view with vector PDF rendering for faces
//  and custom themed back design with flip animation.
//

import SwiftUI

/// A single playing card with elegant design and flip animation.
/// Uses vector PDF rendering for card faces (crisp at any size).
/// Uses custom themed design for card backs.
public struct CardView: View {
    let card: Card
    let isFaceUp: Bool
    let cardWidth: CGFloat
    let theme: any CasinoTheme
    
    public init(
        card: Card,
        isFaceUp: Bool = true,
        cardWidth: CGFloat = CasinoDesign.Size.cardWidth,
        theme: any CasinoTheme = DefaultCasinoTheme()
    ) {
        self.card = card
        self.isFaceUp = isFaceUp
        self.cardWidth = cardWidth
        self.theme = theme
    }
    
    private var cardHeight: CGFloat {
        cardWidth * CasinoDesign.Size.cardAspectRatio
    }
    
    /// Accessibility label describing the card for VoiceOver.
    private var accessibilityDescription: String {
        if isFaceUp {
            return card.accessibilityDescription
        } else {
            return String(localized: "Card face down", bundle: .module)
        }
    }
    
    public var body: some View {
        ZStack {
            if isFaceUp {
                CardFrontView(card: card, width: cardWidth, height: cardHeight, theme: theme)
            } else {
                CardBackView(width: cardWidth, height: cardHeight, theme: theme)
            }
        }
        .rotation3DEffect(
            .degrees(isFaceUp ? 0 : 180),
            axis: (x: 0, y: 1, z: 0)
        )
        .animation(
            .spring(duration: CasinoDesign.Animation.springDuration, bounce: CasinoDesign.Animation.springBounce),
            value: isFaceUp
        )
        .accessibilityLabel(accessibilityDescription)
        .accessibilityAddTraits(.isImage)
    }
}

/// The front face of a playing card using vector PDF rendering.
public struct CardFrontView: View {
    let card: Card
    let width: CGFloat
    let height: CGFloat
    let theme: any CasinoTheme
    
    @State private var image: CGImage?
    
    public init(card: Card, width: CGFloat, height: CGFloat, theme: any CasinoTheme = DefaultCasinoTheme()) {
        self.card = card
        self.width = width
        self.height = height
        self.theme = theme
    }
    
    public var body: some View {
        ZStack {
            // White card background
            RoundedRectangle(cornerRadius: CasinoDesign.CornerRadius.small)
                .fill(Color.white)
            
            // Card face from PDF
            if let image = image {
                Image(decorative: image, scale: 2.0)
                    .resizable()
                    .aspectRatio(contentMode: .fit)
            }
            
            // Subtle border
            RoundedRectangle(cornerRadius: CasinoDesign.CornerRadius.small)
                .strokeBorder(
                    Color.gray.opacity(CasinoDesign.Opacity.light),
                    lineWidth: CasinoDesign.LineWidth.thin
                )
        }
        .frame(width: width, height: height)
        .clipShape(RoundedRectangle(cornerRadius: CasinoDesign.CornerRadius.small))
        .shadow(
            color: .black.opacity(CasinoDesign.Opacity.light),
            radius: CasinoDesign.Shadow.radiusSmall,
            x: CasinoDesign.Shadow.offsetMedium,
            y: CasinoDesign.Shadow.offsetMedium
        )
        .onAppear {
            renderImage()
        }
        .onChange(of: card.pdfIndex) { _, _ in
            renderImage()
        }
    }
    
    private func renderImage() {
        guard width > 0 && height > 0 else { return }
        image = CardRenderer.shared.renderCard(card, size: CGSize(width: width, height: height))
    }
}

/// The back of a playing card with elegant themed pattern.
public struct CardBackView: View {
    let width: CGFloat
    let height: CGFloat
    let theme: any CasinoTheme
    
    // MARK: - Layout Constants
    
    private let innerPaddingRatio: CGFloat = 0.1
    private let patternPaddingRatio: CGFloat = 0.12
    private let emblemGradientRatio: CGFloat = 0.15
    private let emblemSizeRatio: CGFloat = 0.3
    
    public init(width: CGFloat, height: CGFloat, theme: any CasinoTheme = DefaultCasinoTheme()) {
        self.width = width
        self.height = height
        self.theme = theme
    }
    
    public var body: some View {
        ZStack {
            // Base
            RoundedRectangle(cornerRadius: CasinoDesign.CornerRadius.small)
                .fill(
                    LinearGradient(
                        colors: [
                            theme.cardBackSecondaryColor,
                            theme.cardBackPrimaryColor
                        ],
                        startPoint: .topLeading,
                        endPoint: .bottomTrailing
                    )
                )
            
            // Border
            RoundedRectangle(cornerRadius: CasinoDesign.CornerRadius.small)
                .strokeBorder(
                    LinearGradient(
                        colors: [
                            theme.accentLightColor,
                            theme.accentDarkColor
                        ],
                        startPoint: .topLeading,
                        endPoint: .bottomTrailing
                    ),
                    lineWidth: CasinoDesign.LineWidth.medium
                )
            
            // Inner pattern area
            RoundedRectangle(cornerRadius: CasinoDesign.CornerRadius.small / 2)
                .fill(
                    LinearGradient(
                        colors: [
                            theme.cardBackPrimaryColor.opacity(CasinoDesign.Opacity.heavy),
                            theme.cardBackSecondaryColor.opacity(CasinoDesign.Opacity.heavy)
                        ],
                        startPoint: .top,
                        endPoint: .bottom
                    )
                )
                .padding(width * innerPaddingRatio)
            
            // Diamond pattern overlay
            DiamondPatternView()
                .foregroundStyle(theme.accentColor.opacity(CasinoDesign.Opacity.light))
                .padding(width * patternPaddingRatio)
                .clipShape(RoundedRectangle(cornerRadius: CasinoDesign.CornerRadius.small / 2))
            
            // Center emblem
            Circle()
                .fill(
                    RadialGradient(
                        colors: [
                            theme.accentLightColor,
                            theme.accentDarkColor
                        ],
                        center: .center,
                        startRadius: 0,
                        endRadius: width * emblemGradientRatio
                    )
                )
                .frame(width: width * emblemSizeRatio, height: width * emblemSizeRatio)
        }
        .frame(width: width, height: height)
        .shadow(
            color: .black.opacity(CasinoDesign.Opacity.light),
            radius: CasinoDesign.Shadow.radiusSmall,
            x: CasinoDesign.Shadow.offsetMedium,
            y: CasinoDesign.Shadow.offsetMedium
        )
    }
}

/// A decorative diamond pattern for card backs.
public struct DiamondPatternView: View {
    public init() {}
    
    public var body: some View {
        Canvas { context, size in
            let spacing = CasinoDesign.Size.patternSpacing
            let diamondSize = CasinoDesign.Size.patternDiamondSize
            
            for row in stride(from: 0, to: size.height, by: spacing) {
                let offset = Int(row / spacing) % 2 == 0 ? 0 : spacing / 2
                
                for col in stride(from: offset, to: size.width, by: spacing) {
                    let path = Path { p in
                        p.move(to: CGPoint(x: col, y: row - diamondSize / 2))
                        p.addLine(to: CGPoint(x: col + diamondSize / 2, y: row))
                        p.addLine(to: CGPoint(x: col, y: row + diamondSize / 2))
                        p.addLine(to: CGPoint(x: col - diamondSize / 2, y: row))
                        p.closeSubpath()
                    }
                    context.fill(path, with: .foreground)
                }
            }
        }
    }
}

/// A placeholder for an empty card slot.
public struct CardPlaceholderView: View {
    let width: CGFloat
    
    public init(width: CGFloat = CasinoDesign.Size.cardWidth) {
        self.width = width
    }
    
    private var height: CGFloat {
        width * CasinoDesign.Size.cardAspectRatio
    }
    
    public var body: some View {
        RoundedRectangle(cornerRadius: CasinoDesign.CornerRadius.small)
            .strokeBorder(
                Color.white.opacity(CasinoDesign.Opacity.light),
                style: StrokeStyle(
                    lineWidth: CasinoDesign.LineWidth.medium,
                    dash: [CasinoDesign.Size.dashLength, CasinoDesign.Size.dashGap]
                )
            )
            .frame(width: width, height: height)
            .accessibilityLabel(String(localized: "Empty card slot", bundle: .module))
    }
}

// MARK: - Previews

#Preview("Card Views") {
    ZStack {
        Color(red: 0.05, green: 0.35, blue: 0.15)
            .ignoresSafeArea()
        
        VStack(spacing: CasinoDesign.Spacing.large) {
            // Row 1: Face cards
            HStack(spacing: CasinoDesign.Spacing.medium) {
                CardView(card: Card(suit: .hearts, rank: .ace), isFaceUp: true, cardWidth: 70)
                CardView(card: Card(suit: .spades, rank: .king), isFaceUp: true, cardWidth: 70)
                CardView(card: Card(suit: .diamonds, rank: .queen), isFaceUp: true, cardWidth: 70)
                CardView(card: Card(suit: .clubs, rank: .jack), isFaceUp: true, cardWidth: 70)
            }
            
            // Row 2: Number cards
            HStack(spacing: CasinoDesign.Spacing.medium) {
                CardView(card: Card(suit: .hearts, rank: .ten), isFaceUp: true, cardWidth: 70)
                CardView(card: Card(suit: .spades, rank: .seven), isFaceUp: true, cardWidth: 70)
                CardView(card: Card(suit: .diamonds, rank: .four), isFaceUp: true, cardWidth: 70)
                CardView(card: Card(suit: .clubs, rank: .two), isFaceUp: true, cardWidth: 70)
            }
            
            // Row 3: Card back (custom themed design)
            HStack(spacing: CasinoDesign.Spacing.medium) {
                CardView(card: Card(suit: .hearts, rank: .ace), isFaceUp: false, cardWidth: 70)
                CardView(card: Card(suit: .spades, rank: .ace), isFaceUp: false, cardWidth: 70)
            }
        }
    }
}

#Preview("All Suits - Aces") {
    ZStack {
        Color(red: 0.05, green: 0.35, blue: 0.15)
            .ignoresSafeArea()
        
        HStack(spacing: CasinoDesign.Spacing.medium) {
            CardView(card: Card(suit: .spades, rank: .ace), cardWidth: 80)
            CardView(card: Card(suit: .hearts, rank: .ace), cardWidth: 80)
            CardView(card: Card(suit: .clubs, rank: .ace), cardWidth: 80)
            CardView(card: Card(suit: .diamonds, rank: .ace), cardWidth: 80)
        }
    }
}

#Preview("Large Cards") {
    ZStack {
        Color(red: 0.05, green: 0.35, blue: 0.15)
            .ignoresSafeArea()
        
        HStack(spacing: CasinoDesign.Spacing.large) {
            CardView(card: Card(suit: .hearts, rank: .king), cardWidth: 120)
            CardView(card: Card(suit: .spades, rank: .ace), isFaceUp: false, cardWidth: 120)
        }
    }
}
