import ComposableArchitecture
import Foundation
import Localization
import SwiftUI

// MARK: - BirthdayDateFormatters

enum BirthdayDateFormatters {
    static let fieldInputFormatter = DateFormatter(dateFormat: "MM/dd/yyyy")
    static let serverFormatter = DateFormatter(dateFormat: "yyyy-MM-dd")
}

// MARK: - BirthdayFormatting

public enum BirthdayFormatting {
    public static func formatBirthdayInput(_ value: String) -> String {
        let sanitized = value.replacingOccurrences(of: "[^0-9]", with: "", options: .regularExpression)

        // Limit to 8 digits (MMDDYYYY)
        let truncated = String(sanitized.prefix(8))
        var formatted = truncated

        switch truncated.count {
        case 0 ... 1:
            formatted = truncated

        case 2:
            formatted = "\(truncated)/"

        case 3 ... 4:
            formatted = "\(truncated.prefix(2))/\(truncated.dropFirst(2))"
            if formatted.count == 5 {
                formatted = "\(formatted)/"
            }

        default:
            formatted = "\(truncated.prefix(2))/\(truncated.dropFirst(2).prefix(2))/\(truncated.dropFirst(4))"
        }

        return formatted
    }

    public static func validateBirthday(_ formattedValue: String) -> Bool {
        guard let date = BirthdayDateFormatters.fieldInputFormatter.date(from: formattedValue),
              formattedValue.count == "MM/dd/yyyy".count
        else {
            return false
        }

        return isValidAge(date: date)
    }

    public static func isValidAge(date: Date) -> Bool {
        let calendar = Calendar.current
        let now = Date()

        // Prevent future dates
        guard date <= now else { return false }

        // Calculate age
        let ageComponents = calendar.dateComponents([.year], from: date, to: now)
        guard let age = ageComponents.year else { return false }

        // Check age bounds: 3 to 120 years old
        return age >= 3 && age <= 120
    }

    public static func validateBirthdayWithErrorMessage(_ formattedValue: String) -> String? {
        guard let date = BirthdayDateFormatters.fieldInputFormatter.date(from: formattedValue),
              formattedValue.count == "MM/dd/yyyy".count
        else {
            return L10n.FeatureOnboarding.birthdayErrorInvalidDate
        }

        let calendar = Calendar.current
        let now = Date()

        // Prevent future dates
        guard date <= now else {
            return L10n.FeatureOnboarding.birthdayErrorFutureDate
        }

        // Calculate age
        let ageComponents = calendar.dateComponents([.year], from: date, to: now)
        guard let age = ageComponents.year else {
            return L10n.FeatureOnboarding.birthdayErrorInvalidDate
        }

        // Check age bounds: 3 to 120 years old
        if age < 3 {
            return L10n.FeatureOnboarding.birthdayErrorTooYoung
        } else if age > 120 {
            return L10n.FeatureOnboarding.birthdayErrorTooOld
        }

        return nil
    }

    public static func convertBirthdayToServerFormat(_ formattedValue: String) -> String? {
        guard let parsed = BirthdayDateFormatters.fieldInputFormatter.date(from: formattedValue) else { return nil }
        return BirthdayDateFormatters.serverFormatter.string(from: parsed)
    }
}

// MARK: - BirthdayBackspaceHandler

/// A ViewModifier that provides intelligent backspace handling for birthday date fields.
///
/// When a user backspaces on a slash character in a date field (MM/dd/yyyy format),
/// this handler automatically removes both the slash and the preceding digit to provide
/// a more intuitive editing experience.
///
/// Behavior Examples:
/// - "01/23/1990" → User backspaces on the last character → "01/23/199"
/// - "01/23/" → User backspaces on the slash → "01/2" (removes both "/" and "3")
/// - "01/" → User backspaces on the slash → "0" (removes both "/" and "1")
/// - "01/2" → User backspaces on "2" → "01/"

public extension View {
    func birthdayBackspaceHandling(formattedValue: Binding<String>, onFormat: @escaping (String) -> Void) -> some View {
        modifier(BirthdayBackspaceHandler(formattedValue: formattedValue, onFormat: onFormat))
    }
}

private struct BirthdayBackspaceHandler: ViewModifier {
    @Binding var formattedValue: String
    let onFormat: (String) -> Void

    public init(formattedValue: Binding<String>, onFormat: @escaping (String) -> Void) {
        self._formattedValue = formattedValue
        self.onFormat = onFormat
    }

    public func body(content: Content) -> some View {
        content
            .onChange(of: formattedValue) { oldValue, newValue in
                guard oldValue != newValue else { return }

                // Detect if user backspaced on a slash character
                // Example: "01/" → "01" (user pressed backspace)
                // Conditions:
                // 1. oldValue ends with "/" (e.g., "01/")
                // 2. newValue doesn't end with "/" (e.g., "01")
                // 3. oldValue is longer (confirms deletion, not replacement)
                if oldValue.last == "/", newValue.last != "/", oldValue.count > newValue.count {
                    // Remove one more character to delete the digit before the slash
                    // Example: "01" → "0" (removes the "1" that was before the slash)
                    onFormat(String(newValue.dropLast()))
                } else {
                    // Normal case: just pass through the new value
                    // Examples:
                    // - Regular typing: "0" → "01"
                    // - Normal backspace: "012" → "01"
                    // - After slash addition: "01" → "01/"
                    onFormat(newValue)
                }
            }
    }
}
