import SwiftUI
import ComposeApp

// FIX_SKIPPED: LE-2 — This view calls APILayer directly (loadUsers, loadShareCode,
// generateShareCode, removeUser). Fixing requires extracting a dedicated ManageUsersViewModel.
// Architectural refactor deferred — requires new ViewModel.
struct ManageUsersView: View {
    let residenceId: Int32
    let residenceName: String
    let isPrimaryOwner: Bool
    let residenceOwnerId: Int32
    let residence: ResidenceResponse?
    @Environment(\.dismiss) private var dismiss

    @State private var users: [ResidenceUserResponse]
    private var ownerId: Int32 { residenceOwnerId }
    @State private var shareCode: ShareCodeResponse?
    @State private var isLoading: Bool
    @State private var errorMessage: String?
    @State private var isGeneratingCode = false
    @State private var shareFileURL: URL?
    @ObservedObject private var sharingManager = ResidenceSharingManager.shared

    /// Default init used by the app. `onAppear` calls `loadUsers()`
    /// which fetches via APILayer. Starts in the loading state.
    init(
        residenceId: Int32,
        residenceName: String,
        isPrimaryOwner: Bool,
        residenceOwnerId: Int32,
        residence: ResidenceResponse?
    ) {
        self.residenceId = residenceId
        self.residenceName = residenceName
        self.isPrimaryOwner = isPrimaryOwner
        self.residenceOwnerId = residenceOwnerId
        self.residence = residence
        self._users = State(initialValue: [])
        self._isLoading = State(initialValue: true)
    }

    /// Snapshot-test / preview init that pre-seeds the `users` list and
    /// skips the loading state. Lets `ManageUsersView` render its
    /// populated list of residence collaborators on the first composition
    /// frame, bypassing the APILayer round-trip that fails hermetically.
    init(
        residenceId: Int32,
        residenceName: String,
        isPrimaryOwner: Bool,
        residenceOwnerId: Int32,
        residence: ResidenceResponse?,
        initialUsers: [ResidenceUserResponse]
    ) {
        self.residenceId = residenceId
        self.residenceName = residenceName
        self.isPrimaryOwner = isPrimaryOwner
        self.residenceOwnerId = residenceOwnerId
        self.residence = residence
        self._users = State(initialValue: initialUsers)
        self._isLoading = State(initialValue: false)
    }

    var body: some View {
        NavigationStack {
            ZStack {
                WarmGradientBackground()

                // Prefer rendering the users list whenever we have
                // one — handles pre-seeded snapshot-test / preview
                // state and avoids flashing a spinner over already-
                // visible content during a background refresh.
                if !users.isEmpty {
                    scrollBody
                } else if isLoading {
                    ProgressView()
                } else if let error = errorMessage {
                    ErrorView(message: error) {
                        loadUsers()
                    }
                } else {
                    scrollBody
                }
            }
            .listStyle(.plain)
            .scrollContentBackground(.hidden)
            .navigationTitle(L10n.Residences.manageUsers)
            .navigationBarTitleDisplayMode(.inline)
            .toolbar {
                ToolbarItem(placement: .navigationBarTrailing) {
                    Button(L10n.Common.close) {
                        dismiss()
                    }
                }
            }
        }
        .onAppear {
            // Skip auto-load if the view was pre-seeded with users
            // (snapshot-test / preview path). Otherwise proceed with
            // the normal authenticated fetch.
            if users.isEmpty {
                shareCode = nil
                loadUsers()
                loadShareCode()
            }
        }
        .sheet(isPresented: Binding(
            get: { shareFileURL != nil },
            set: { if !$0 { shareFileURL = nil } }
        )) {
            if let url = shareFileURL {
                ShareSheet(activityItems: [url])
            }
        }
        .alert("Error", isPresented: Binding(
            get: { sharingManager.errorMessage != nil },
            set: { if !$0 { sharingManager.errorMessage = nil } }
        )) {
            Button("OK", role: .cancel) {}
        } message: {
            Text(sharingManager.errorMessage ?? "Failed to create share link.")
        }
    }

    /// Populated/empty-state scroll body. Factored out so the "we have
    /// users" branch and the "no-data empty state" branch can share the
    /// same share-code card + users list shell.
    @ViewBuilder
    private var scrollBody: some View {
        ScrollView {
            VStack(spacing: 16) {
                // Share code section (primary owner only)
                if isPrimaryOwner {
                    ShareCodeCard(
                        shareCode: shareCode,
                        isGeneratingCode: isGeneratingCode,
                        isGeneratingPackage: sharingManager.isGeneratingPackage,
                        onGenerateCode: generateShareCode,
                        onEasyShare: easyShare
                    )
                    .padding(.horizontal)
                    .padding(.top)
                }

                // Users list
                VStack(alignment: .leading, spacing: 12) {
                    Text("\(L10n.Residences.users) (\(users.count))")
                        .font(.headline)
                        .padding(.horizontal)

                    ForEach(users, id: \.id) { user in
                        UserListItem(
                            user: user,
                            isOwner: user.id == ownerId,
                            isPrimaryOwner: isPrimaryOwner,
                            onRemove: {
                                removeUser(userId: user.id)
                            }
                        )
                    }
                }
                .padding(.bottom)
            }
        }
        .accessibilityIdentifier("ManageUsers.UsersList")
    }

    private func easyShare() {
        guard let residence = residence else { return }

        Task {
            if let url = await sharingManager.createShareableFile(residence: residence) {
                shareFileURL = url
            }
        }
    }

    private func loadUsers() {
        guard TokenStorage.shared.getToken() != nil else {
            errorMessage = "Not authenticated"
            return
        }

        isLoading = true
        errorMessage = nil

        Task {
            do {
                let result = try await APILayer.shared.getResidenceUsers(residenceId: Int32(Int(residenceId)))

                await MainActor.run {
                    if let successResult = result as? ApiResultSuccess<NSArray>,
                       let responseData = successResult.data as? [ResidenceUserResponse] {
                        self.users = responseData
                        self.isLoading = false
                    } else if let errorResult = ApiResultBridge.error(from: result) {
                        self.errorMessage = ErrorMessageParser.parse(errorResult.message)
                        self.isLoading = false
                    } else {
                        self.errorMessage = "Failed to load users"
                        self.isLoading = false
                    }
                }
            } catch {
                await MainActor.run {
                    self.errorMessage = ErrorMessageParser.parse(error.localizedDescription)
                    self.isLoading = false
                }
            }
        }
    }

    private func loadShareCode() {
        guard TokenStorage.shared.getToken() != nil else { return }

        Task {
            do {
                let result = try await APILayer.shared.getShareCode(residenceId: Int32(Int(residenceId)))

                await MainActor.run {
                    if let successResult = result as? ApiResultSuccess<ShareCodeResponse> {
                        self.shareCode = successResult.data
                    }
                    // It's okay if there's no active share code
                }
            } catch {
                // It's okay if there's no active share code
            }
        }
    }

    private func generateShareCode() {
        guard TokenStorage.shared.getToken() != nil else { return }

        isGeneratingCode = true

        Task {
            do {
                let result = try await APILayer.shared.generateShareCode(residenceId: Int32(Int(residenceId)))

                await MainActor.run {
                    if let successResult = result as? ApiResultSuccess<GenerateShareCodeResponse>,
                       let response = successResult.data {
                        self.shareCode = response.shareCode
                        self.isGeneratingCode = false
                    } else if let errorResult = ApiResultBridge.error(from: result) {
                        self.errorMessage = ErrorMessageParser.parse(errorResult.message)
                        self.isGeneratingCode = false
                    } else {
                        self.errorMessage = "Failed to generate share code"
                        self.isGeneratingCode = false
                    }
                }
            } catch {
                await MainActor.run {
                    self.errorMessage = ErrorMessageParser.parse(error.localizedDescription)
                    self.isGeneratingCode = false
                }
            }
        }
    }

    private func removeUser(userId: Int32) {
        guard TokenStorage.shared.getToken() != nil else { return }

        Task {
            do {
                let result = try await APILayer.shared.removeUser(residenceId: Int32(Int(residenceId)), userId: Int32(Int(userId)))

                await MainActor.run {
                    if result is ApiResultSuccess<RemoveUserResponse> {
                        // Remove user from local list
                        self.users.removeAll { $0.id == userId }
                    } else if let errorResult = ApiResultBridge.error(from: result) {
                        self.errorMessage = ErrorMessageParser.parse(errorResult.message)
                    } else {
                        self.errorMessage = "Failed to remove user"
                    }
                }
            } catch {
                await MainActor.run {
                    self.errorMessage = ErrorMessageParser.parse(error.localizedDescription)
                }
            }
        }
    }
}

#Preview {
    ManageUsersView(residenceId: 1, residenceName: "My Home", isPrimaryOwner: true, residenceOwnerId: 1, residence: nil)
}
