import SwiftUI

struct WorkspacesSettingsView: View {
    @ObservedObject private var workspaceRegistry = WorkspaceRegistry.shared
    @ObservedObject private var screenRegistry = ScreenRegistry.shared

    @State private var selectedWorkspaceID: WorkspaceID?
    @State private var renameDraft = ""
    @State private var isDeleteAlertPresented = false

    private var effectiveSelectedWorkspaceID: WorkspaceID? {
        selectedWorkspaceID ?? workspaceRegistry.workspaceSummaries.first?.id
    }

    private var selectedSummary: WorkspaceSummary? {
        guard let effectiveSelectedWorkspaceID else { return nil }
        return workspaceRegistry.summary(for: effectiveSelectedWorkspaceID)
    }

    private var selectedController: WorkspaceController? {
        guard let effectiveSelectedWorkspaceID else { return nil }
        return workspaceRegistry.controller(for: effectiveSelectedWorkspaceID)
    }

    private var selectedAssignedScreenIDs: [ScreenID] {
        guard let effectiveSelectedWorkspaceID else { return [] }
        return screenRegistry.assignedScreenIDs(to: effectiveSelectedWorkspaceID)
    }

    private var connectedScreenSummaries: [ConnectedScreenSummary] {
        screenRegistry.connectedScreenSummaries()
    }

    private var activeConnectedScreenSummary: ConnectedScreenSummary? {
        connectedScreenSummaries.first(where: \.isActive)
    }

    private var deletionFallbackSummary: WorkspaceSummary? {
        guard let effectiveSelectedWorkspaceID,
              let fallbackID = workspaceRegistry.deletionFallbackWorkspaceID(
                forDeleting: effectiveSelectedWorkspaceID,
                preferredFallback: workspaceRegistry.defaultWorkspaceID
              ) else {
            return nil
        }

        return workspaceRegistry.summary(for: fallbackID)
    }

    var body: some View {
        HStack(spacing: 20) {
            List(selection: $selectedWorkspaceID) {
                ForEach(workspaceRegistry.workspaceSummaries) { summary in
                    VStack(alignment: .leading, spacing: 4) {
                        Text(summary.name)
                            .font(.headline)

                        Text(usageDescription(for: summary))
                            .font(.caption)
                            .foregroundStyle(.secondary)
                    }
                    .tag(summary.id)
                    .accessibilityIdentifier("settings.workspace.row.\(summary.id.uuidString)")
                }
            }
            .accessibilityIdentifier("settings.workspaces.list")
            .frame(minWidth: 220, idealWidth: 240, maxWidth: 260, maxHeight: .infinity)

            if let summary = selectedSummary {
                Form {
                    Section("Identity") {
                        TextField("Workspace name", text: $renameDraft)
                            .accessibilityIdentifier("settings.workspaces.name-field")
                            .onSubmit {
                                renameSelectedWorkspace()
                            }

                        OptionalHotkeyRecorderView(
                            label: "Jump Hotkey",
                            binding: workspaceHotkeyBinding(for: summary.id)
                        )

                        HStack {
                            Button("Save Name") {
                                renameSelectedWorkspace()
                            }
                            .accessibilityIdentifier("settings.workspaces.save-name")

                            Button("New Workspace") {
                                createWorkspace()
                            }
                            .accessibilityIdentifier("settings.workspaces.new")
                        }

                        Text("Workspace jump hotkeys are active when the notch is open and switch the current screen to this workspace.")
                            .font(.caption)
                            .foregroundStyle(.secondary)
                    }

                    Section("Usage") {
                        LabeledContent("Assigned screens") {
                            Text("\(selectedAssignedScreenIDs.count)")
                                .accessibilityIdentifier("settings.workspaces.assigned-count")
                        }

                        LabeledContent("Open tabs") {
                            Text("\(selectedController?.tabs.count ?? 0)")
                        }

                        if selectedAssignedScreenIDs.isEmpty {
                            Text("No screens are currently assigned to this workspace.")
                                .foregroundStyle(.secondary)
                        } else {
                            ForEach(selectedAssignedScreenIDs, id: \.self) { screenID in
                                LabeledContent("Screen") {
                                    Text(screenID)
                                        .font(.caption.monospaced())
                                }
                            }
                        }
                    }

                    Section("Shared Workspace Rules") {
                        Text(sharedWorkspaceDescription(for: selectedAssignedScreenIDs.count))
                            .foregroundStyle(.secondary)
                    }

                    Section("Connected Screens") {
                        if let activeScreen = activeConnectedScreenSummary {
                            HStack {
                                VStack(alignment: .leading, spacing: 4) {
                                    Text(activeScreen.displayName)
                                    Text(activeScreen.id)
                                        .font(.caption.monospaced())
                                        .foregroundStyle(.secondary)
                                }

                                Spacer()

                                Button(activeScreen.assignedWorkspaceID == summary.id ? "Assigned Here" : "Assign Current Screen") {
                                    screenRegistry.assignWorkspace(summary.id, to: activeScreen.id)
                                }
                                .accessibilityIdentifier("settings.workspaces.assign-current")
                                .disabled(activeScreen.assignedWorkspaceID == summary.id)
                            }
                        } else {
                            Text("No connected screens are currently available.")
                                .foregroundStyle(.secondary)
                        }

                        ForEach(connectedScreenSummaries.filter { !$0.isActive }) { screen in
                            HStack {
                                VStack(alignment: .leading, spacing: 4) {
                                    Text(screen.displayName)
                                    Text(screen.id)
                                        .font(.caption.monospaced())
                                        .foregroundStyle(.secondary)
                                }

                                Spacer()

                                Button(screen.assignedWorkspaceID == summary.id ? "Assigned Here" : "Assign Here") {
                                    screenRegistry.assignWorkspace(summary.id, to: screen.id)
                                }
                                .accessibilityIdentifier("settings.workspaces.assign.\(screen.id)")
                                .disabled(screen.assignedWorkspaceID == summary.id)
                            }
                        }
                    }

                    Section("Danger Zone") {
                        Button("Delete Workspace", role: .destructive) {
                            isDeleteAlertPresented = true
                        }
                        .accessibilityIdentifier("settings.workspaces.delete")
                        .disabled(!workspaceRegistry.canDeleteWorkspace(id: summary.id))

                        if !workspaceRegistry.canDeleteWorkspace(id: summary.id) {
                            Text("At least one workspace must remain.")
                                .foregroundStyle(.secondary)
                        }
                    }
                }
                .formStyle(.grouped)
            } else {
                ContentUnavailableView(
                    "No Workspaces",
                    systemImage: "rectangle.3.group",
                    description: Text("Create a workspace to start grouping tabs across screens.")
                )
            }
        }
        .onAppear {
            selectInitialWorkspaceIfNeeded()
        }
        .onChange(of: workspaceRegistry.workspaceSummaries) { _, _ in
            synchronizeSelectionWithRegistry()
        }
        .onChange(of: selectedWorkspaceID) { _, _ in
            renameDraft = selectedSummary?.name ?? ""
        }
        .alert("Delete Workspace", isPresented: $isDeleteAlertPresented) {
            Button("Cancel", role: .cancel) {}
            Button("Delete", role: .destructive) {
                deleteSelectedWorkspace()
            }
        } message: {
            if let summary = selectedSummary, let fallback = deletionFallbackSummary {
                Text(
                    "Deleting \(summary.name) reassigns its screens to \(fallback.name) and closes the workspace."
                )
            } else {
                Text("At least one workspace must remain.")
            }
        }
    }

    private func usageDescription(for summary: WorkspaceSummary) -> String {
        let screenCount = screenRegistry.assignedScreenCount(to: summary.id)
        let tabCount = workspaceRegistry.controller(for: summary.id)?.tabs.count ?? 0
        return "\(screenCount) screen\(screenCount == 1 ? "" : "s") · \(tabCount) tab\(tabCount == 1 ? "" : "s")"
    }

    private func sharedWorkspaceDescription(for screenCount: Int) -> String {
        if screenCount > 1 {
            return "This workspace is shared across \(screenCount) screens. Tab changes stay in sync across each assigned screen."
        }

        if screenCount == 1 {
            return "This workspace is assigned to one screen. You can assign additional screens to share the same tabs."
        }

        return "Unassigned workspaces keep their tabs and can be attached to any screen later."
    }

    private func selectInitialWorkspaceIfNeeded() {
        if selectedWorkspaceID == nil {
            selectedWorkspaceID = workspaceRegistry.workspaceSummaries.first?.id
        }
        renameDraft = selectedSummary?.name ?? ""
    }

    private func synchronizeSelectionWithRegistry() {
        guard let selectedWorkspaceID else {
            selectInitialWorkspaceIfNeeded()
            return
        }

        if workspaceRegistry.summary(for: selectedWorkspaceID) == nil {
            self.selectedWorkspaceID = workspaceRegistry.workspaceSummaries.first?.id
        }

        renameDraft = selectedSummary?.name ?? ""
    }

    private func renameSelectedWorkspace() {
        guard let effectiveSelectedWorkspaceID else { return }
        workspaceRegistry.renameWorkspace(id: effectiveSelectedWorkspaceID, to: renameDraft)
        renameDraft = selectedSummary?.name ?? renameDraft
    }

    private func createWorkspace() {
        let workspaceID = workspaceRegistry.createWorkspace()
        selectedWorkspaceID = workspaceID
        renameDraft = workspaceRegistry.summary(for: workspaceID)?.name ?? ""
    }

    private func workspaceHotkeyBinding(for workspaceID: WorkspaceID) -> Binding<HotkeyBinding?> {
        Binding(
            get: {
                workspaceRegistry.summary(for: workspaceID)?.hotkey
            },
            set: { newValue in
                workspaceRegistry.updateWorkspaceHotkey(id: workspaceID, to: newValue)
            }
        )
    }

    private func deleteSelectedWorkspace() {
        guard let effectiveSelectedWorkspaceID,
              let fallbackWorkspaceID = screenRegistry.deleteWorkspace(
                effectiveSelectedWorkspaceID,
                preferredFallback: workspaceRegistry.defaultWorkspaceID
              ) else {
            return
        }

        self.selectedWorkspaceID = fallbackWorkspaceID
        renameDraft = workspaceRegistry.summary(for: fallbackWorkspaceID)?.name ?? ""
    }
}
