import ComponentLibrary
import SwiftNavigation
import SwiftUI

public struct MadlibsStyledTextField: View {
    private enum Constants {
        static let textFieldAutoFocusDelay: TimeInterval = 0.3
        static let textFieldCharacterLimit = 40

        static let inputHeight: CGFloat = 56
        static let horizontalPadding: CGFloat = 20
        static let clearButtonSize: CGFloat = 20

        static let typography = TypographyV1.headline5.neueMontrealMedium()
    }

    let title: String
    let subtitle: String?
    let placeholder: String
    let autofillContentType: UITextContentType?
    @Binding var value: String
    @Binding var focused: Bool
    let isLoading: Bool
    let onClear: () -> Void
    let errorMessage: String?

    @FocusState private var focusedState: Bool

    public init(
        title: String,
        subtitle: String? = nil,
        placeholder: String,
        autofillContentType: UITextContentType?,
        value: Binding<String>,
        focused: Binding<Bool>,
        isLoading: Bool = false,
        onClear: @escaping () -> Void,
        errorMessage: String? = nil
    ) {
        self.title = title
        self.subtitle = subtitle
        self.placeholder = placeholder
        self.autofillContentType = autofillContentType
        self._value = value
        self._focused = focused
        self.isLoading = isLoading
        self.onClear = onClear
        self.errorMessage = errorMessage
    }

    public var body: some View {
        MadlibsLayoutView(title: title, subtitle: subtitle) {
            VStack(spacing: 32) {
                VStack(alignment: .leading, spacing: 8) {
                    HStack {
                        TextField("", text: $value.limit(Constants.textFieldCharacterLimit))
                            .typographyV1(Constants.typography)
                            .foregroundColor(Color.SemanticV1.alwaysLighterBeige)
                            .tint(Color.SemanticV2.accentBrand)
                            .focused($focusedState)
                            .textInputAutocapitalization(.words)
                            .autocorrectionDisabled()
                            .textContentType(autofillContentType)
                            .placeholder(when: value.isEmpty) {
                                HStack {
                                    Text(placeholder)
                                        .typographyV1(Constants.typography)
                                        .foregroundStyle(Color.SemanticV1.textSecondary)
                                        .lineLimit(1)
                                        .minimumScaleFactor(0.8)

                                    Spacer()
                                }
                            }

                        if !value.isEmpty {
                            Button(
                                action: onClear,
                                label: {
                                    Image.Icon.close
                                        .foregroundColor(Color.SemanticV1.alwaysLighterBeige)
                                        .font(.system(size: Constants.clearButtonSize))
                                }
                            )
                            .disabled(isLoading)
                            .opacity(isLoading ? 0.4 : 1.0)
                            .transition(.opacity.animation(.easeInOut(duration: 0.2)))
                        }
                    }
                    .frame(height: Constants.inputHeight)
                    .padding(.horizontal, Constants.horizontalPadding)
                    .background(Color.SemanticV2.backgroundFogThin)
                    .clipShape(Capsule())
                    .bind($focused, to: $focusedState)

                    if let errorMessage {
                        Text(errorMessage)
                            .typographyV1(.caption.neueMontrealRegular())
                            .foregroundColor(Color.SemanticV1.textWarning)
                            .padding(.horizontal, Constants.horizontalPadding)
                            .transition(.opacity.combined(with: .move(edge: .top)))
                            .animation(.easeInOut(duration: 0.2), value: errorMessage)
                    }
                }

                Spacer()
            }
        }
        .onAppear {
            // If focus is already set (e.g., during keyboard persistence), apply immediately
            if focused {
                focusedState = true
            } else {
                // Otherwise, use delay for smooth appearance
                DispatchQueue.main.asyncAfter(deadline: .now() + Constants.textFieldAutoFocusDelay) {
                    focusedState = true
                }
            }
        }
    }
}
