import SwiftUI
import UIKit

struct SetPasswordView: View {
    let seedPhrase: [String]
    let isImportMode: Bool
    let onAccountCreated: () -> Void
    let onBack: () -> Void

    @State private var password = ""
    @State private var confirmPassword = ""
    @State private var isCreating = false
    @State private var errorMessage: String?
    @State private var focusedField: Field?
    @State private var showWeakPasswordAlert = false

    fileprivate enum Field {
        case password, confirm
    }

    private var passwordsMatch: Bool {
        !password.isEmpty && password == confirmPassword
    }

    private var canCreate: Bool {
        passwordsMatch && !isCreating
    }

    private var matchesDesktopPasswordPolicy: Bool {
        password.range(of: "[A-Z]+", options: .regularExpression) != nil &&
        password.range(of: "[0-9]+", options: .regularExpression) != nil &&
        password.range(of: "[$@#&!]+", options: .regularExpression) != nil
    }

    var body: some View {
        VStack(spacing: 0) {
            AuthNavigationBar(onBack: onBack)

            ScrollView(showsIndicators: false) {
                VStack(spacing: 20) {
                    lockIcon
                    headerSection

                    VStack(spacing: 8) {
                        passwordField
                        PasswordStrengthIndicator(password: password)
                    }

                    VStack(spacing: 8) {
                        confirmField
                        PasswordMatchIndicator(password: password, confirmPassword: confirmPassword)
                    }

                    WeakPasswordWarning(password: password)

                    if let message = errorMessage {
                        Text(message)
                            .font(.system(size: 13))
                            .foregroundStyle(RosettaColors.error)
                            .multilineTextAlignment(.center)
                            .transition(.opacity.combined(with: .scale(scale: 0.95)))
                    }
                }
                .padding(.horizontal, 24)
                .padding(.top, 8)
                .padding(.bottom, 32)
            }
            .scrollDismissesKeyboard(.interactively)
            .onTapGesture(count: 1) { focusedField = nil }
            .simultaneousGesture(TapGesture().onEnded {})

            Spacer()

            VStack(spacing: 16) {
                infoCard
                createButton
            }
            .padding(.horizontal, 24)
            .padding(.bottom, 16)
        }
        .ignoresSafeArea(.keyboard)
        .alert("Insecure password", isPresented: $showWeakPasswordAlert) {
            Button("I'll come up with a new one", role: .cancel) {}
            Button("Continue") {
                performAccountCreation()
            }
        } message: {
            Text("Your password is insecure. Such passwords are easy to guess. Choose a stronger one, or continue anyway.")
        }
    }
}

// MARK: - Lock Icon

private extension SetPasswordView {
    var lockIcon: some View {
        GlassCard(cornerRadius: 20, fillOpacity: 0.1) {
            Image(systemName: "lock.shield.fill")
                .font(.system(size: 32))
                .foregroundStyle(RosettaColors.primaryBlue)
                .frame(width: 72, height: 72)
        }
        .accessibilityHidden(true)
    }
}

// MARK: - Header

private extension SetPasswordView {
    var headerSection: some View {
        VStack(spacing: 8) {
            Text(isImportMode ? "Recover Account" : "Protect Your Account")
                .font(.system(size: 24, weight: .bold))
                .foregroundStyle(RosettaColors.Adaptive.text)

            Text(isImportMode
                 ? "Set a password to protect your recovered account.\nYou'll need it to unlock Rosetta."
                 : "This password encrypts your keys locally.\nYou'll need it to unlock Rosetta.")
                .font(.system(size: 14))
                .foregroundStyle(RosettaColors.Adaptive.textSecondary)
                .multilineTextAlignment(.center)
                .lineSpacing(2)
        }
        .accessibilityElement(children: .combine)
    }
}

// MARK: - Password Fields

private extension SetPasswordView {
    var passwordField: some View {
        secureInputField(placeholder: "Password", text: $password, field: .password)
            .accessibilityLabel("Password input")
    }

    var confirmField: some View {
        secureInputField(placeholder: "Confirm Password", text: $confirmPassword, field: .confirm)
            .accessibilityLabel("Confirm password input")
    }

    func secureInputField(
        placeholder: String,
        text: Binding<String>,
        field: Field
    ) -> some View {
        SecureToggleField(
            text: text,
            placeholder: placeholder,
            field: field,
            focusedField: $focusedField
        )
        .frame(height: 50)
        .background {
            RoundedRectangle(cornerRadius: 12)
                .fill(RosettaColors.cardFill)
                .overlay {
                    RoundedRectangle(cornerRadius: 12)
                        .stroke(
                            focusedField == field
                                ? RosettaColors.primaryBlue
                                : RosettaColors.subtleBorder,
                            lineWidth: focusedField == field ? 2 : 1
                        )
                }
        }
    }
}

// MARK: - Info Card

private extension SetPasswordView {
    var infoCard: some View {
        GlassCard(cornerRadius: 12, fillOpacity: 0.08) {
            HStack(alignment: .top, spacing: 10) {
                Image(systemName: "info.circle.fill")
                    .foregroundStyle(RosettaColors.primaryBlue)
                    .font(.system(size: 16))

                Text("Your password is never stored or sent anywhere. It's only used to encrypt your keys locally.")
                    .font(.system(size: 13))
                    .foregroundStyle(RosettaColors.Adaptive.textSecondary)
                    .lineSpacing(2)
            }
            .padding(16)
        }
        .accessibilityElement(children: .combine)
        .accessibilityLabel("Your password is only used for local encryption and is never sent anywhere.")
    }
}

// MARK: - Create Button

private extension SetPasswordView {
    @ViewBuilder
    var createButton: some View {
        Button(action: createAccount) {
            Group {
                if isCreating {
                    ProgressView()
                        .tint(.white)
                } else {
                    Text(isImportMode ? "Recover Account" : "Create Account")
                        .font(.system(size: 16, weight: .semibold))
                        .foregroundStyle(.white)
                }
            }
            .frame(maxWidth: .infinity)
            .frame(height: 56)
        }
        .buttonStyle(RosettaPrimaryButtonStyle(isEnabled: canCreate))
        .shine(tintColor: canCreate
               ? Color(red: 0.35, green: 0.82, blue: 0.98).opacity(0.50)
               : .clear)
        .accessibilityHint(canCreate ? "Creates your encrypted account" : "Enter matching passwords first")
    }

    func createAccount() {
        guard canCreate else { return }
        guard matchesDesktopPasswordPolicy else {
            showWeakPasswordAlert = true
            return
        }
        performAccountCreation()
    }

    func performAccountCreation() {
        guard canCreate else { return }
        isCreating = true

        Task {
            do {
                _ = try await AccountManager.shared.createAccount(
                    seedPhrase: seedPhrase,
                    password: password
                )
                // Start session (WebSocket + handshake) immediately after account creation
                try await SessionManager.shared.startSession(password: password)
                isCreating = false
                onAccountCreated()
            } catch {
                isCreating = false
                errorMessage = error.localizedDescription
            }
        }
    }
}

// MARK: - Fixed Height Text Field

/// UITextField subclass with locked intrinsicContentSize and custom rect overrides.
/// Handles internal padding (16pt left, 46pt right for eye button) and rightView positioning.
/// Prevents any layout propagation to SwiftUI when isSecureTextEntry toggles.
private final class FixedHeightTextField: UITextField {
    override var intrinsicContentSize: CGSize {
        CGSize(width: UIView.noIntrinsicMetric, height: 50)
    }

    override func textRect(forBounds bounds: CGRect) -> CGRect {
        bounds.inset(by: UIEdgeInsets(top: 0, left: 16, bottom: 0, right: 46))
    }

    override func editingRect(forBounds bounds: CGRect) -> CGRect {
        textRect(forBounds: bounds)
    }

    override func rightViewRect(forBounds bounds: CGRect) -> CGRect {
        CGRect(x: bounds.width - 16 - 30, y: (bounds.height - 30) / 2, width: 30, height: 30)
    }

    override func placeholderRect(forBounds bounds: CGRect) -> CGRect {
        textRect(forBounds: bounds)
    }
}

// MARK: - Secure Toggle Field (UIKit)

/// Wraps UIKit's UITextField with a built-in eye toggle button as rightView.
/// The toggle happens entirely in UIKit — no SwiftUI @State changes, no body re-evaluation,
/// no ScrollView layout pass. This eliminates the "input expanding" bug.
private struct SecureToggleField: UIViewRepresentable {
    @Binding var text: String
    var placeholder: String
    var field: SetPasswordView.Field
    @Binding var focusedField: SetPasswordView.Field?

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

    func makeUIView(context: Context) -> FixedHeightTextField {
        let tf = FixedHeightTextField()
        context.coordinator.textField = tf

        tf.isSecureTextEntry = true
        tf.font = .systemFont(ofSize: 16)
        tf.textColor = .label
        tf.tintColor = UIColor(RosettaColors.primaryBlue)
        tf.autocapitalizationType = .none
        tf.autocorrectionType = .no
        tf.spellCheckingType = .no
        tf.textContentType = .init(rawValue: "")
        tf.inputAccessoryView = UIView(frame: .zero)
        tf.returnKeyType = .done
        tf.backgroundColor = .clear
        tf.setContentHuggingPriority(.required, for: .vertical)
        tf.setContentCompressionResistancePriority(.required, for: .vertical)

        tf.delegate = context.coordinator
        tf.addTarget(
            context.coordinator,
            action: #selector(Coordinator.textChanged(_:)),
            for: .editingChanged
        )
        tf.attributedPlaceholder = NSAttributedString(
            string: placeholder,
            attributes: [.foregroundColor: UIColor(RosettaColors.tertiaryText)]
        )

        // Eye toggle button — entirely UIKit, no SwiftUI state involved
        let config = UIImage.SymbolConfiguration(pointSize: 14, weight: .thin)
        let eyeButton = UIButton(type: .system)
        eyeButton.setImage(UIImage(systemName: "eye", withConfiguration: config), for: .normal)
        eyeButton.tintColor = UIColor.secondaryLabel
        eyeButton.addTarget(
            context.coordinator,
            action: #selector(Coordinator.toggleSecure),
            for: .touchUpInside
        )
        eyeButton.frame = CGRect(x: 0, y: 0, width: 30, height: 30)
        eyeButton.accessibilityLabel = "Show password"
        tf.rightView = eyeButton
        tf.rightViewMode = .always

        return tf
    }

    func updateUIView(_ tf: FixedHeightTextField, context: Context) {
        context.coordinator.parent = self

        // Sync text (only if different to avoid cursor jump)
        if tf.text != text { tf.text = text }

        // Sync focus (deferred to avoid re-entrant layout)
        let wantsFocus = focusedField == field
        if wantsFocus && !tf.isFirstResponder {
            DispatchQueue.main.async { tf.becomeFirstResponder() }
        } else if !wantsFocus && tf.isFirstResponder {
            DispatchQueue.main.async { tf.resignFirstResponder() }
        }
    }

    /// Lock the size SwiftUI sees — prevents intrinsicContentSize changes
    /// from propagating as layout invalidations.
    func sizeThatFits(
        _ proposal: ProposedViewSize,
        uiView: FixedHeightTextField,
        context: Context
    ) -> CGSize? {
        CGSize(width: proposal.width ?? 200, height: 50)
    }

    final class Coordinator: NSObject, UITextFieldDelegate {
        var parent: SecureToggleField
        weak var textField: FixedHeightTextField?

        init(parent: SecureToggleField) { self.parent = parent }

        @objc func textChanged(_ tf: UITextField) {
            parent.text = tf.text ?? ""
        }

        /// Toggle isSecureTextEntry entirely in UIKit — no SwiftUI @State change.
        @objc func toggleSecure() {
            guard let tf = textField else { return }
            UIView.performWithoutAnimation {
                let existingText = tf.text
                tf.isSecureTextEntry.toggle()
                // iOS clears text when toggling isSecureTextEntry — restore it
                tf.text = ""
                tf.text = existingText

                // Update eye icon
                let imageName = tf.isSecureTextEntry ? "eye" : "eye.slash"
                let config = UIImage.SymbolConfiguration(pointSize: 14, weight: .thin)
                let button = tf.rightView as? UIButton
                button?.setImage(
                    UIImage(systemName: imageName, withConfiguration: config),
                    for: .normal
                )
                button?.accessibilityLabel = tf.isSecureTextEntry
                    ? "Show password"
                    : "Hide password"
            }
        }

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

        func textFieldDidBeginEditing(_ textField: UITextField) {
            parent.focusedField = parent.field
        }

        func textFieldDidEndEditing(_ textField: UITextField) {
            if parent.focusedField == parent.field {
                parent.focusedField = nil
            }
        }
    }
}

#Preview {
    SetPasswordView(
        seedPhrase: ["abandon", "ability", "able", "about", "above", "absent",
                     "absorb", "abstract", "absurd", "abuse", "access", "accident"],
        isImportMode: false,
        onAccountCreated: {},
        onBack: {}
    )
    .preferredColorScheme(.dark)
    .background(RosettaColors.authBackground)
}
