//
//  TimeDisplayView.swift
//  TheNoiseClock
//
//  Created by Matt Bruce on 9/7/25.
//

import SwiftUI
import Bedrock

/// Component for displaying segmented time with customizable formatting
struct TimeDisplayView: View {
    
    // MARK: - Debug Configuration
    /// When true, shows static "88:88:88" to debug font sizing
    private static let debugStaticTime = false
    /// When true, shows debug overlays with sizing info
    private static let debugShowOverlays = false
    /// Static hour value for debug mode
    private static let debugHour = "88"
    /// Static minute value for debug mode
    private static let debugMinute = "88"
    /// Static seconds value for debug mode
    private static let debugSeconds = "88"
    
    // MARK: - Properties
    let date: Date
    let use24Hour: Bool
    let showSeconds: Bool
    let showAmPm: Bool
    let digitColor: Color
    let glowIntensity: Double
    let clockOpacity: Double
    let fontFamily: FontFamily
    let fontWeight: Font.Weight
    let fontDesign: Font.Design
    let forceHorizontalMode: Bool
    let isDisplayMode: Bool
    let animationStyle: DigitAnimationStyle
    @State var fontSize: CGFloat = 100
    @State private var lastCalculatedContainerSize: CGSize = .zero
    
    // MARK: - Layout Constants
    private enum Layout {
        static let dotDiameterMultiplier: CGFloat = 0.65
        static let dotSpacingPortraitMultiplier: CGFloat = 0.16
        static let dotSpacingLandscapeMultiplier: CGFloat = 0.22
    }
    
    // MARK: - Formatters
    private static let hour24DF: DateFormatter = {
        let df = DateFormatter()
        df.locale = Locale(identifier: "en_US_POSIX")
        df.dateFormat = "HH"
        return df
    }()
    
    private static let hour12DF: DateFormatter = {
        let df = DateFormatter()
        df.locale = Locale(identifier: "en_US_POSIX")
        df.dateFormat = "h"
        return df
    }()
    
    private static let minuteDF: DateFormatter = {
        let df = DateFormatter()
        df.locale = Locale(identifier: "en_US_POSIX")
        df.dateFormat = "mm"
        return df
    }()
    
    private static let amPmDF: DateFormatter = {
        let df = DateFormatter()
        df.locale = Locale(identifier: "en_US_POSIX")
        df.dateFormat = "a"
        return df
    }()
    
    private static let secondDF: DateFormatter = {
        let df = DateFormatter()
        df.locale = Locale(identifier: "en_US_POSIX")
        df.dateFormat = "ss"
        return df
    }()
    
    // MARK: - Body
    var body: some View {
        return GeometryReader { proxy in
            let containerSize = proxy.size
            let portraitMode = containerSize.height >= containerSize.width
            let portrait = !forceHorizontalMode && containerSize.height >= containerSize.width

            // Time components - use debug static values if enabled
            let hour: String
            let minute: String
            let secondsText: String
            
            if Self.debugStaticTime {
                hour = Self.debugHour
                minute = Self.debugMinute
                secondsText = Self.debugSeconds
            } else {
                hour = use24Hour ? Self.hour24DF.string(from: date) : Self.hour12DF.string(from: date)
                minute = Self.minuteDF.string(from: date)
                secondsText = Self.secondDF.string(from: date)
            }
            
            
            // AM/PM badge - hide in debug mode
            let shouldShowAmPm = !Self.debugStaticTime && showAmPm && !use24Hour
            let amPmText = Self.debugStaticTime ? "" : Self.amPmDF.string(from: date).uppercased()
            
            // Separators - reasonable spacing with extra padding in landscape
            let dotDiameter = fontSize * Layout.dotDiameterMultiplier
            let dotSpacing = portrait
            ? fontSize * Layout.dotSpacingPortraitMultiplier
            : fontSize * Layout.dotSpacingLandscapeMultiplier
            
            // Time display with consistent centering and stable layout
            return Group {
                if portrait {
                    VStack(alignment: .center, spacing: 0) {
                        TimeSegment(text: hour, fontSize: $fontSize, opacity: clockOpacity, digitColor: digitColor, glowIntensity: glowIntensity, fontFamily: fontFamily, fontWeight: fontWeight, fontDesign: fontDesign, isDisplayMode: isDisplayMode, animationStyle: animationStyle)
                        ColonView(dotDiameter: dotDiameter, spacing: dotSpacing, opacity: clockOpacity, digitColor: digitColor, glowIntensity: glowIntensity, fontWeight: fontWeight, isHorizontal: true)
                        TimeSegment(text: minute, fontSize: $fontSize, opacity: clockOpacity, digitColor: digitColor, glowIntensity: glowIntensity, fontFamily: fontFamily, fontWeight: fontWeight, fontDesign: fontDesign, isDisplayMode: isDisplayMode, animationStyle: animationStyle)
                        if showSeconds {
                            ColonView(dotDiameter: dotDiameter, spacing: dotSpacing, opacity: clockOpacity, digitColor: digitColor, glowIntensity: glowIntensity, fontWeight: fontWeight, isHorizontal: true)
                            TimeSegment(text: secondsText, fontSize: $fontSize, opacity: clockOpacity, digitColor: digitColor, glowIntensity: glowIntensity, fontFamily: fontFamily, fontWeight: fontWeight, fontDesign: fontDesign, isDisplayMode: isDisplayMode, animationStyle: animationStyle)
                        }
                    }
                    .frame(maxWidth: .infinity) // Center horizontally in portrait
                } else {
                    // Landscape mode - use fixed digit widths for stable layout
                    // Each digit gets the same width (based on "8") so clock doesn't shift
                    let fixedDigitWidth = FontUtils.digitWidth(
                        fontName: fontFamily,
                        weight: fontWeight,
                        design: fontDesign,
                        fontSize: fontSize
                    )
                    let segmentWidth = fixedDigitWidth * 2 // Minutes/seconds always 2 digits
                    // Hour width is dynamic based on actual digit count (1 or 2 digits)
                    let hourSegmentWidth = fixedDigitWidth * CGFloat(hour.count)
                    
                    HStack(alignment: .center, spacing: 0) {
                        TimeSegment(text: hour, fontSize: $fontSize, opacity: clockOpacity, digitColor: digitColor, glowIntensity: glowIntensity, fontFamily: fontFamily, fontWeight: fontWeight, fontDesign: fontDesign, isDisplayMode: isDisplayMode, animationStyle: animationStyle)
                            .frame(width: hourSegmentWidth)
                        ColonView(dotDiameter: dotDiameter, spacing: dotSpacing, opacity: clockOpacity, digitColor: digitColor, glowIntensity: glowIntensity, fontWeight: fontWeight, isHorizontal: false)
                            .frame(width: dotDiameter)
                        TimeSegment(text: minute, fontSize: $fontSize, opacity: clockOpacity, digitColor: digitColor, glowIntensity: glowIntensity, fontFamily: fontFamily, fontWeight: fontWeight, fontDesign: fontDesign, isDisplayMode: isDisplayMode, animationStyle: animationStyle)
                            .frame(width: segmentWidth)
                        if showSeconds {
                            ColonView(dotDiameter: dotDiameter, spacing: dotSpacing, opacity: clockOpacity, digitColor: digitColor, glowIntensity: glowIntensity, fontWeight: fontWeight, isHorizontal: false)
                                .frame(width: dotDiameter)
                            TimeSegment(text: secondsText, fontSize: $fontSize, opacity: clockOpacity, digitColor: digitColor, glowIntensity: glowIntensity, fontFamily: fontFamily, fontWeight: fontWeight, fontDesign: fontDesign, isDisplayMode: isDisplayMode, animationStyle: animationStyle)
                                .frame(width: segmentWidth)
                        }
                    }
                    .frame(maxWidth: .infinity, maxHeight: .infinity) // Center in landscape
                }
            }
            .overlay(alignment: .bottomTrailing) {
                if shouldShowAmPm {
                    Text(amPmText)
                        .font(
                            FontUtils.createFont(
                                name: fontFamily,
                                weight: fontWeight,
                                design: fontDesign,
                                size: max(12, fontSize * 0.18)
                            )
                        )
                        .foregroundColor(digitColor)
                        .opacity(clockOpacity)
                        .padding(.horizontal, max(6, fontSize * 0.05))
                        .padding(.vertical, max(3, fontSize * 0.03))
                }
            }
            .offset(y: portraitMode && forceHorizontalMode ? -containerSize.height * 0.10 : 0) // Push up in horizontal mode
            .animation(.smooth(duration: Design.Animation.standard), value: showSeconds) // Smooth animation for seconds toggle
            .minimumScaleFactor(0.1)
            .clipped() // Prevent overflow beyond bounds
            .overlay(alignment: .topLeading) {
                if Self.debugShowOverlays {
                    debugInfoOverlay(containerSize: containerSize, portrait: portrait)
                }
            }
            .debugBorder(Self.debugShowOverlays, color: .cyan, label: "TimeDisplayView")
            .onAppear {
                updateFontSize(containerSize: containerSize, portrait: portrait, showSeconds: showSeconds)
            }
            .onChange(of: containerSize) { _, newSize in
                updateFontSize(containerSize: newSize, portrait: portrait, showSeconds: showSeconds)
            }
            .onChange(of: showSeconds) { _, _ in
                updateFontSize(containerSize: containerSize, portrait: portrait, showSeconds: showSeconds)
            }
            .onChange(of: fontFamily) { _, _ in
                updateFontSize(containerSize: containerSize, portrait: portrait, showSeconds: showSeconds)
            }
            .onChange(of: fontWeight) { _, _ in
                updateFontSize(containerSize: containerSize, portrait: portrait, showSeconds: showSeconds)
            }
            .onChange(of: fontDesign) { _, _ in
                updateFontSize(containerSize: containerSize, portrait: portrait, showSeconds: showSeconds)
            }
        }
        .frame(maxWidth: .infinity, maxHeight: .infinity)
        .onOrientationChange() // Force updates on orientation changes
    }
    
    // MARK: - Debug Overlay
    @ViewBuilder
    private func debugInfoOverlay(containerSize: CGSize, portrait: Bool) -> some View {
        let digitColumns: CGFloat = portrait ? 2.0 : (showSeconds ? 6.0 : 4.0)
        let digitRows: CGFloat = portrait ? (showSeconds ? 3.0 : 2.0) : 1.0
        let colonCount: CGFloat = showSeconds ? 2.0 : 1.0
        let colonSize = fontSize * Layout.dotDiameterMultiplier
        
        let availableWidth = portrait
            ? containerSize.width
            : max(1, containerSize.width - (colonCount * colonSize))
        let availableHeight = portrait
            ? max(1, containerSize.height - (colonCount * colonSize))
            : containerSize.height
        let digitSlotSize = CGSize(
            width: max(1, availableWidth / digitColumns),
            height: max(1, availableHeight / digitRows)
        )
        
        VStack(alignment: .leading, spacing: 2) {
            Text("Container: \(Int(containerSize.width))×\(Int(containerSize.height))")
            Text("Digit Slot: \(Int(digitSlotSize.width))×\(Int(digitSlotSize.height))")
            Text("Font Size: \(Int(fontSize))")
            Text("Cols: \(Int(digitColumns)) Rows: \(Int(digitRows))")
            Text("Portrait: \(portrait)")
            Text("Family: \(fontFamily.rawValue)")
        }
        .font(.system(size: 10, weight: .bold, design: .monospaced))
        .foregroundStyle(.yellow)
        .padding(4)
        .background(Color.black.opacity(0.7))
        .clipShape(.rect(cornerRadius: 4))
        .padding(8)
    }
    
    // MARK: - Font Sizing
    private func updateFontSize(containerSize: CGSize, portrait: Bool, showSeconds: Bool) {
        guard containerSize != .zero else { return }
        
        let digitColumns: CGFloat = portrait ? 2.0 : (showSeconds ? 6.0 : 4.0)
        let digitRows: CGFloat = portrait ? (showSeconds ? 3.0 : 2.0) : 1.0
        let colonCount: CGFloat = showSeconds ? 2.0 : 1.0
        let previousFontSize = fontSize
        
        func calculateFontSize(reservingColonSize colonSize: CGFloat) -> CGFloat {
            let availableWidth = portrait
            ? containerSize.width
            : max(1, containerSize.width - (colonCount * colonSize))
            let availableHeight = portrait
            ? max(1, containerSize.height - (colonCount * colonSize))
            : containerSize.height
            let digitSize = CGSize(
                width: max(1, availableWidth / digitColumns),
                height: max(1, availableHeight / digitRows)
            )
            
            //Design.debugLog("[clockLayout] calcFont size=\(String(format: "%.1f", containerSize.width))x\(String(format: "%.1f", containerSize.height)) portrait=\(portrait) seconds=\(showSeconds)")
            //Design.debugLog("[clockLayout] calcFont available=\(String(format: "%.1f", availableWidth))x\(String(format: "%.1f", availableHeight)) columns=\(String(format: "%.1f", digitColumns)) rows=\(String(format: "%.1f", digitRows)) colonCount=\(String(format: "%.1f", colonCount))")
            //Design.debugLog("[clockLayout] calcFont digitSize=\(String(format: "%.1f", digitSize.width))x\(String(format: "%.1f", digitSize.height)) colonSize=\(String(format: "%.1f", colonSize))")
            
            return FontUtils.calculateOptimalFontSize(
                digit: "8",
                fontName: fontFamily,
                weight: fontWeight,
                design: fontDesign,
                for: digitSize,
                isDisplayMode: isDisplayMode
            )
        }
        
        var estimated = calculateFontSize(reservingColonSize: 0)
        for _ in 0..<2 {
            let dotDiameter = estimated * Layout.dotDiameterMultiplier
            estimated = calculateFontSize(reservingColonSize: dotDiameter)
        }
        
        if !portrait {
            // Verify colon height fits
            let dotDiameter = estimated * Layout.dotDiameterMultiplier
            let dotSpacing = estimated * Layout.dotSpacingLandscapeMultiplier
            let colonHeight = (dotDiameter * 2) + dotSpacing
            if colonHeight > containerSize.height {
                estimated *= containerSize.height / colonHeight
            }
            
            // CRITICAL: Verify total width fits to prevent clipping
            // Calculate actual widths that will be used in layout
            let actualDigitWidth = FontUtils.digitWidth(
                fontName: fontFamily,
                weight: fontWeight,
                design: fontDesign,
                fontSize: estimated
            )
            let actualColonWidth = estimated * Layout.dotDiameterMultiplier
            let segmentCount: CGFloat = showSeconds ? 3.0 : 2.0
            let totalWidth = (actualDigitWidth * 2 * segmentCount) + (colonCount * actualColonWidth)
            
            // If total width exceeds container, scale down
            if totalWidth > containerSize.width {
                let scaleFactor = containerSize.width / totalWidth
                estimated *= scaleFactor * 0.98 // Add 2% margin
                //Design.debugLog("[clockLayout] width overflow: totalWidth=\(Int(totalWidth)) container=\(Int(containerSize.width)) scaling by \(String(format: "%.2f", scaleFactor))")
            }
        }
        
        //Design.debugLog("[clockLayout] calcFont estimatedFontSize=\(String(format: "%.1f", estimated))")

        if abs(estimated - fontSize) > 1 {
            fontSize = estimated
            //Design.debugLog("[clockLayout] calcFont updated fontSize \(String(format: "%.1f", previousFontSize)) -> \(String(format: "%.1f", fontSize))")
        } else {
           // Design.debugLog("[clockLayout] calcFont skipped update (current=\(String(format: "%.1f", previousFontSize)))")
        }
        lastCalculatedContainerSize = containerSize
    }
}


// MARK: - Preview
#Preview {
    TimeDisplayView(
        date: Date(),
        use24Hour: true,
        showSeconds: false,
        showAmPm: true,
        digitColor: .white,
        glowIntensity: 0.2,
        clockOpacity: 1.0,
        fontFamily: .verdana,
        fontWeight: .medium,
        fontDesign: .default,
        forceHorizontalMode: false,
        isDisplayMode: false,
        animationStyle: .spring
    )
    .background(Color.black)
}
