import Foundation
import SwiftUI
import Combine

public struct Input: View {
    @Binding public var text: String
    
    public var placeholder: String
    public var floatingValue: String
    public var floatingIcon: String
    public var floatingIconColor: Color
    public var size: InputSize
    public var hintText: String
    public var error: String
    public var errorSpacing: Bool
    public var disabled: Bool
    public var readOnly: Bool
    public var secureTextEntry: Bool
    public var rightIcon: String
    public var rightIconColor: Color
    public var leadingIcon: String
    public var leadingIconColor: Color
    public var loading: Bool
    public var required: Bool
    public var maxLength: Int?
    public var fontWeight: InputFontWeight
    public var keyboardType: UIKeyboardType
    public var autofocus: Bool
    public var onChangeText: ((String) -> Void)?
    public var onFocus: (() -> Void)?
    public var onBlur: (() -> Void)?
    public var onRightIconPressed: (() -> Void)?
    
    @State private var isFocused: Bool = false
    @State private var isPasswordHidden: Bool = true
    
    public init(
        text: Binding<String>,
        placeholder: String = "",
        floatingValue: String = "",
        floatingIcon: String = "",
        floatingIconColor: Color = Colors.primary,
        size: InputSize = .small,
        hintText: String = "",
        error: String = "",
        errorSpacing: Bool = false,
        disabled: Bool = false,
        readOnly: Bool = false,
        secureTextEntry: Bool = false,
        rightIcon: String = "",
        rightIconColor: Color = Colors.black17,
        leadingIcon: String = "",
        leadingIconColor: Color = Colors.black12,
        loading: Bool = false,
        required: Bool = false,
        maxLength: Int? = nil,
        fontWeight: InputFontWeight = .regular,
        keyboardType: UIKeyboardType = .default,
        autofocus: Bool = false,
        onChangeText: ((String) -> Void)? = nil,
        onFocus: (() -> Void)? = nil,
        onBlur: (() -> Void)? = nil,
        onRightIconPressed: (() -> Void)? = nil
    ) {
        self._text = text
        self.placeholder = placeholder
        self.floatingValue = floatingValue
        self.floatingIcon = floatingIcon
        self.floatingIconColor = floatingIconColor
        self.size = size
        self.hintText = hintText
        self.error = error
        self.errorSpacing = errorSpacing
        self.disabled = disabled
        self.readOnly = readOnly
        self.secureTextEntry = secureTextEntry
        self.rightIcon = rightIcon
        self.rightIconColor = rightIconColor
        self.leadingIcon = leadingIcon
        self.leadingIconColor = leadingIconColor
        self.loading = loading
        self.required = required
        self.maxLength = maxLength
        self.fontWeight = fontWeight
        self.keyboardType = keyboardType
        self.autofocus = autofocus
        self.onChangeText = onChangeText
        self.onFocus = onFocus
        self.onBlur = onBlur
        self.onRightIconPressed = onRightIconPressed
    }

    // MARK: - Body
    public var body: some View {
        let textBinding = Binding<String>(
            get: { self.text },
            set: { newValue in
                self.text = newValue
                self.onChangeText?(limitText(newValue))
            }
        )

        VStack(alignment: .leading, spacing: 4) {
            ZStack(alignment: .topLeading) {
                // Floating label
                if !floatingValue.isEmpty || !floatingIcon.isEmpty {
                    HStack(spacing: Spacing.XS) {
                        MomoText(floatingValue, typography: .labelSMedium, color: getFloatingColor())
                        if required {
                            MomoText("*", typography: .labelSMedium, color: Colors.red03)
                        }
                        if !floatingIcon.isEmpty {
                            Icon(source: floatingIcon, size: 16, color: getFloatingIconColor())
                        }
                    }
                    .padding(.horizontal, Spacing.S)
                    .background(Colors.black01)
                    .offset(x: Spacing.S, y: -8)
                    .zIndex(10)
                }
                
                // Input container
                HStack(alignment: .center, spacing: 0) {
                    // Leading icon
                    if !leadingIcon.isEmpty {
                        Icon(source: leadingIcon, size: size == .small ? 24 : 32, color: leadingIconColor)
                            .padding(.trailing, Spacing.M)
                    }
                    
                    // Text input field
                    ZStack(alignment: .leading) {
                        if text.isEmpty {
                            MomoText(
                                placeholder + (required && floatingValue.isEmpty ? " *" : ""),
                                typography: fontWeight == .bold ? .actionSBold : .bodyDefaultRegular,
                                color: getPlaceholderColor()
                            )
                        }
                        
                        if secureTextEntry && isPasswordHidden {
                            SecureInputField(
                                text: $text,
                                keyboardType: keyboardType,
                                fontSize: scaleSize(14),
                                fontWeight: fontWeight == .bold ? .bold : .regular,
                                textColor: UIColor(getTextColor()),
                                isDisabled: disabled || readOnly,
                                maxLength: maxLength,
                                onFocusChange: { focused in
                                    handleFocusChange(focused)
                                },
                                onChangeText: onChangeText
                            )
                        } else {
                            TextField("", text: textBinding, onEditingChanged: { focused in
                                handleFocusChange(focused)
                            })
                            .keyboardType(keyboardType)
                            .font(fontWeight == .bold ? .action_s_bold : .body_default_regular)
                            .foregroundColor(getTextColor())
                            .disabled(disabled || readOnly)
                            .applyPrimaryCursorColor()
                            .onChange(of: text) { newValue in
                                let limited = limitText(newValue)
                                if limited != newValue {
                                    text = limited
                                }
                            }
                        }
                    }
                    
                    // Clear button (only show when focused and has text)
                    if isFocused && !text.isEmpty {
                        SwiftUI.Button(action: {
                            text = ""
                            onChangeText?("")
                        }) {
                            Icon(source: "24_navigation_close_circle_full", size: 16, color: Colors.black12)
                                .padding(.leading, Spacing.S).accessibility(identifier: "ic_clear")
                        }
                    }
                    
                    // Loading indicator
                    if loading {
                        ActivityIndicator(isAnimating: .constant(true), style: .medium)
                            .frame(width: 16, height: 16)
                            .padding(.leading, Spacing.S)
                    }
                    
                    // Right icon (password toggle or custom icon)
                    if secureTextEntry {
                        if !text.isEmpty {
                            SwiftUI.Button(action: togglePasswordVisibility) {
                                Icon(
                                    source: isPasswordHidden ? "24_security_eye_off" : "24_security_eye_open",
                                    size: 24,
                                    color: rightIconColor
                                )
                                .padding(.leading, Spacing.S).accessibility(identifier: "ic_show_hide")
                            }
                        }
                    } else if !rightIcon.isEmpty {
                        SwiftUI.Button(action: { onRightIconPressed?() }) {
                            Icon(source: rightIcon, size: 24, color: rightIconColor)
                                .padding(.leading, Spacing.S)
                        }
                    }
                }
                .padding(.horizontal, Spacing.M)
                .frame(height: scaleSize(size == .small ? 48 : 56, 1.1))
                .background(
                    RoundedRectangle(cornerRadius: Radius.S)
                        .fill(Colors.black01)
                )
                .overlay(
                    RoundedRectangle(cornerRadius: Radius.S)
                        .stroke(borderColor(), lineWidth: 1)
                )
            }
            
            // Error or hint
            ErrorView(
                errorMessage: error,
                errorSpacing: errorSpacing,
                hintText: hintText
            )
        }
        .onReceive(NotificationCenter.default.publisher(for: UIResponder.keyboardWillHideNotification)) { _ in
            if isFocused && !secureTextEntry {
                DispatchQueue.main.async {
                    handleFocusChange(false)
                }
            }
        }
    }
    
    // MARK: - Helpers
    
    private func handleFocusChange(_ focused: Bool) {
        isFocused = focused
        if focused {
            onFocus?()
        } else {
            onBlur?()
        }
    }
    
    private func togglePasswordVisibility() {
        isPasswordHidden.toggle()
        onRightIconPressed?()
    }

    private func limitText(_ value: String) -> String {
        guard let maxLength = maxLength else {
            return value
        }
        return String(value.prefix(maxLength))
    }
    
    private func borderColor() -> Color {
        if disabled {
            return Colors.black04 // border.disable
        }
        if !error.isEmpty {
            return Colors.red03 // error.primary
        }
        if isFocused {
            return Colors.primary
        }
        return Colors.black04 // border.default
    }
    
    private func getTextColor() -> Color {
        return disabled ? Colors.black09 : Colors.black17
    }
    
    private func getPlaceholderColor() -> Color {
        return disabled ? Colors.black09 : Colors.black12
    }
    
    private func getFloatingColor() -> Color {
        return disabled ? Colors.black09 : Colors.black12
    }
    
    private func getFloatingIconColor() -> Color {
        return disabled ? Colors.black09 : floatingIconColor
    }
}


// MARK: - Secure Input Field (UIViewRepresentable)
private struct SecureInputField: UIViewRepresentable {
    @Binding var text: String
    var keyboardType: UIKeyboardType
    var fontSize: CGFloat
    var fontWeight: UIFont.Weight
    var textColor: UIColor
    var isDisabled: Bool
    var maxLength: Int?
    var onFocusChange: (Bool) -> Void
    var onChangeText: ((String) -> Void)?

    func makeCoordinator() -> Coordinator {
        Coordinator(self)
    }

    func makeUIView(context: Context) -> UITextField {
        let textField = UITextField()
        textField.isSecureTextEntry = true
        textField.delegate = context.coordinator
        textField.keyboardType = keyboardType
        textField.font = UIFont.systemFont(ofSize: fontSize, weight: fontWeight)
        textField.textColor = textColor
        textField.isEnabled = !isDisabled
        textField.setContentHuggingPriority(.defaultLow, for: .horizontal)
        textField.setContentCompressionResistancePriority(.defaultLow, for: .horizontal)
        textField.text = text
        textField.tintColor = UIColor(Colors.primary)
        textField.addTarget(
            context.coordinator,
            action: #selector(Coordinator.textFieldDidChange(_:)),
            for: .editingChanged
        )
        return textField
    }

    func updateUIView(_ textField: UITextField, context: Context) {
        context.coordinator.parent = self
        if textField.text != text {
            textField.text = text
        }
        textField.isEnabled = !isDisabled
        if textField.keyboardType != keyboardType {
            textField.keyboardType = keyboardType
            textField.reloadInputViews()
        }
    }

    class Coordinator: NSObject, UITextFieldDelegate {
        var parent: SecureInputField
        private var isResettingText = false

        init(_ parent: SecureInputField) {
            self.parent = parent
        }

        func textFieldDidBeginEditing(_ textField: UITextField) {
            let existingText = textField.text ?? ""
            if !existingText.isEmpty {
                // When a secure text field regains focus, iOS marks the
                // existing text as "committed". The next keystroke would
                // replace ALL committed text with the new character.
                // Prevent this by clearing and re-inserting via insertText(),
                // which puts the text into an "active editing" state.
                isResettingText = true
                textField.text = ""
                textField.insertText(existingText)
                isResettingText = false
            }
            parent.onFocusChange(true)
        }

        func textFieldDidEndEditing(_ textField: UITextField) {
            parent.text = limitText(textField.text ?? "")
            parent.onFocusChange(false)
        }

        func textField(
            _ textField: UITextField,
            shouldChangeCharactersIn range: NSRange,
            replacementString string: String
        ) -> Bool {
            if isResettingText { return true }
            return true
        }

        @objc func textFieldDidChange(_ textField: UITextField) {
            if isResettingText { return }
            let newText = limitText(textField.text ?? "")
            if textField.text != newText {
                textField.text = newText
            }
            parent.text = newText
            parent.onChangeText?(newText)
        }

        func textFieldShouldReturn(_ textField: UITextField) -> Bool {
            textField.resignFirstResponder()
            return true
        }

        private func limitText(_ value: String) -> String {
            guard let maxLength = parent.maxLength else {
                return value
            }
            return String(value.prefix(maxLength))
        }
    }
}

// MARK: - Helper Extension
private extension View {
    func applyPrimaryCursorColor() -> some View {
        if #available(iOS 15.0, *) {
            return self.tint(Colors.primary)
        } else {
            return self
        }
    }
}

// MARK: - Activity Indicator
struct ActivityIndicator: UIViewRepresentable {
    @Binding var isAnimating: Bool
    let style: UIActivityIndicatorView.Style

    func makeUIView(context: UIViewRepresentableContext<ActivityIndicator>) -> UIActivityIndicatorView {
        return UIActivityIndicatorView(style: style)
    }

    func updateUIView(_ uiView: UIActivityIndicatorView, context: UIViewRepresentableContext<ActivityIndicator>) {
        isAnimating ? uiView.startAnimating() : uiView.stopAnimating()
    }
}

// MARK: - Enums
public enum InputSize {
    case small
    case large
}

public enum InputFontWeight {
    case regular
    case bold
}
