//
//  DigitView.swift
//  TheNoiseClock
//
//  Created by Matt Bruce on 9/9/25.
//

import SwiftUI
import Bedrock

/// Component for displaying a single digit with fixed width and glow effects
struct DigitView: View {
    
    // MARK: - Debug Configuration
    private static let debugShowBorders = false
    
    let digit: String
    let fontName: FontFamily
    let weight: Font.Weight
    let design: Font.Design
    let opacity: Double
    let digitColor: Color
    let glowIntensity: Double
    let isDisplayMode: Bool
    let animationStyle: DigitAnimationStyle
    @Binding var fontSize: CGFloat
    
    init(digit: String,
         fontName: FontFamily,
         weight: Font.Weight = .regular,
         design: Font.Design = .default,
         digitColor: Color = .black,
         opacity: Double = 1,
         glowIntensity: Double = 0,
         fontSize: Binding<CGFloat>,
         isDisplayMode: Bool = false,
         animationStyle: DigitAnimationStyle = .spring) {
        self.digit = (digit.count == 1 && "0123456789".contains(digit)) ? digit : "0"
        self.fontName = fontName
        self.weight = weight
        self.design = design
        self.opacity = opacity
        self.digitColor = digitColor
        self.glowIntensity = glowIntensity
        self.isDisplayMode = isDisplayMode
        self.animationStyle = animationStyle
        self._fontSize = fontSize
    }
    
    var body: some View {
        ZStack {
            glowText
            mainText
        }
        .frame(maxWidth: .infinity, maxHeight: .infinity)
    }
    
    private var glowRadius: CGFloat {
        ColorUtils.glowRadius(intensity: glowIntensity)
    }
    
    private var glowOpacity: Double {
        ColorUtils.glowOpacity(intensity: glowIntensity) * opacity
    }
    
    private var glowText: some View {
        baseText
            .foregroundColor(digitColor)
            .blur(radius: glowRadius)
            .opacity(glowOpacity)
            .modifier(GlowAnimationModifier(style: animationStyle, digit: digit, glowRadius: glowRadius, glowOpacity: glowOpacity))
    }
    
    private var mainText: some View {
        baseText
            .foregroundColor(digitColor)
            .opacity(opacity)
            .modifier(DigitAnimationModifier(style: animationStyle, digit: digit, fontSize: fontSize))
            .debugBorder(Self.debugShowBorders, color: .orange, label: "Text")
    }
    
    private var baseText: some View {
        Text(digit)
            .font(FontUtils.createFont(name: fontName,
                                       weight: weight,
                                       design: design,
                                       size: fontSize))
            .lineLimit(1)
    }
}

// MARK: - Animation Modifiers

private struct DigitAnimationModifier: ViewModifier {
    let style: DigitAnimationStyle
    let digit: String
    let fontSize: CGFloat
    
    func body(content: Content) -> some View {
        switch style {
        case .none:
            content
        case .spring:
            content
                .contentTransition(.numericText())
                .animation(.snappy(duration: 0.35), value: digit)
                .phaseAnimator([0, 1], trigger: digit) { content, phase in
                    content
                        .scaleEffect(phase == 1 ? 1.05 : 1.0)
                        .offset(y: phase == 1 ? -fontSize * 0.02 : 0)
                } animation: { _ in
                    .spring(duration: 0.3, bounce: 0.4)
                }
        case .bounce:
            content
                .contentTransition(.numericText())
                .animation(.bouncy(duration: 0.4), value: digit)
                .phaseAnimator([0, 1], trigger: digit) { content, phase in
                    content
                        .scaleEffect(phase == 1 ? 1.1 : 1.0)
                } animation: { _ in
                    .spring(duration: 0.4, bounce: 0.5)
                }
        case .glitch:
            content
                .contentTransition(.numericText())
                .phaseAnimator([0, 1, 2, 0], trigger: digit) { content, phase in
                    content
                        .offset(x: phase == 1 ? -fontSize * 0.05 : (phase == 2 ? fontSize * 0.05 : 0))
                        .opacity(phase == 1 || phase == 2 ? 0.7 : 1.0)
                        .scaleEffect(phase == 1 ? 1.02 : (phase == 2 ? 0.98 : 1.0))
                } animation: { _ in
                    .interactiveSpring(response: 0.1, dampingFraction: 0.8)
                }
        }
    }
}

private struct GlowAnimationModifier: ViewModifier {
    let style: DigitAnimationStyle
    let digit: String
    let glowRadius: CGFloat
    let glowOpacity: Double
    
    func body(content: Content) -> some View {
        switch style {
        case .none:
            content
        case .spring, .bounce:
            content
                .phaseAnimator([0, 1], trigger: digit) { content, phase in
                    content
                        .blur(radius: glowRadius * (phase == 1 ? 1.5 : 1.0))
                        .opacity(glowOpacity * (phase == 1 ? 1.2 : 1.0))
                } animation: { _ in
                    .easeInOut(duration: 0.3)
                }
        case .glitch:
            content
                .phaseAnimator([0, 1, 2, 0], trigger: digit) { content, phase in
                    content
                        .opacity(phase == 1 || phase == 2 ? 0.4 : 1.0)
                        .blur(radius: glowRadius * (phase == 1 || phase == 2 ? 2.0 : 1.0))
                } animation: { _ in
                    .easeInOut(duration: 0.1)
                }
        }
    }
}

// MARK: - Preview
#Preview {
    @Previewable @State var sharedFontSize: CGFloat = 2000
    @Previewable @State var fontName: FontFamily = .arial
    @Previewable @State var weight: Font.Weight = .heavy
    @Previewable @State var design: Font.Design = .rounded
    @Previewable @State var glowIntensity: Double = 0.6
    
    HStack {
        DigitView(digit: "8",
                  fontName: fontName,
                  weight: weight,
                  design: design,
                  glowIntensity: glowIntensity,
                  fontSize: $sharedFontSize,
                  animationStyle: .spring)
            .border(Color.black)
        
        DigitView(digit: "1",
                  fontName: fontName,
                  weight: weight,
                  design: design,
                  glowIntensity: glowIntensity,
                  fontSize: $sharedFontSize,
                  animationStyle: .spring)
            .border(Color.black)
        
        Text(":")
            .font(.system(size: sharedFontSize))
            .border(Color.black)
        
        DigitView(digit: "0",
                  fontName: fontName,
                  weight: weight,
                  design: design,
                  glowIntensity: glowIntensity,
                  fontSize: $sharedFontSize,
                  animationStyle: .spring)
            .border(Color.black)
        
        DigitView(digit: "5",
                  fontName: fontName,
                  weight: weight,
                  design: design,
                  glowIntensity: glowIntensity,
                  fontSize: $sharedFontSize,
                  animationStyle: .spring)
            .border(Color.black)
    }
}
