import SwiftUI
import HealthKit
import HealthKitExtensions
import HealthDB
import SFSafeSymbols

struct DatabasesTab: View {

    @ObservedObject
    var database: Database

    @ObservedObject
    var databases: DatabaseList

    @State var navigationPath: NavigationPath = .init()

    @State
    private var showFailedToOpenAlert = false

    @State 
    private var showDocumentPicker = false

    @State
    private var showOptionsForSelectedDatabase = false

    @State
    private var changedDatabaseName: String = ""

    @State
    private var showChangeDatabaseNameAlert = false

    @State
    private var selectedDatabase: DatabaseFile? = nil

    private var openCloseButtonText: String {
        database.file == selectedDatabase ? "Close" : "Open"
    }

    private var defaultSelectionButtonText: String {
        (selectedDatabase?.isDefault ?? false) ? "Remove as default" : "Set as default"
    }

    private func symbol(for database: DatabaseFile) -> SFSymbol {
        self.database.file == database ? .circleInsetFilled : .circle
    }

    var body: some View {
        NavigationStack(path: $navigationPath) {
            List {
                ForEach(databases.databases) { database in
                    HStack(alignment: .center) {
                        Image(systemSymbol: symbol(for: database))
                        VStack(alignment: .leading) {
                            HStack(alignment: .firstTextBaseline) {
                                Text(database.name)
                                    .font(.headline)
                                if database.isDefault {
                                    Text("(Default)")
                                        .font(.caption)
                                }
                            }
                            Text(database.file)
                                .font(.caption)
                        }
                    }
                    .onTapGesture {
                        self.selectedDatabase = database
                        self.showOptionsForSelectedDatabase = true
                    }
                }.onDelete(perform: databases.deleteDatabases)
            }
            .navigationTitle("Databases")
            .toolbar {
                Button(action: displayDocumentPicker) {
                    Label("Add", systemSymbol: .plus)
                }
            }
            .fileImporter(isPresented: $showDocumentPicker, 
                          allowedContentTypes: [.database],
                          onCompletion: handle)
            .confirmationDialog("Change background", isPresented: $showOptionsForSelectedDatabase) {
                Button(openCloseButtonText, action: openOrCloseSelectedDatabase)
                Button("Rename", action: renameSelectedDatabase)
                Button(defaultSelectionButtonText, action: toggleDefaultForSelectedDatabase)
                Button("Cancel", role: .cancel) { }
            } message: {
                Text("Select a new color")
            }
            .alert("Update name", isPresented: $showChangeDatabaseNameAlert, actions: {
                TextField("Name", text: $changedDatabaseName)
                Button("Update", action: saveNewNameForSelectedDatabase)
                Button("Cancel", role: .cancel, action: {})
            }, message: {
                Text("Please enter the new name for the database")
            })
            .alert("Failed to open", isPresented: $showFailedToOpenAlert) {
                Button("Dismiss", role: .cancel, action: {})
            } message: {
                Text("The selected database could not be opened. Make sure that it is a valid Health database.")
            }

        }.onAppear(perform: databases.load)
    }

    private func openOrCloseSelectedDatabase() {
        guard let selectedDatabase else { return }
        defer { self.selectedDatabase = nil }

        guard database.load(database: selectedDatabase) else {
            return
        }
    }

    private func renameSelectedDatabase() {
        guard let selectedDatabase else { return }
        self.changedDatabaseName = selectedDatabase.name
        self.showChangeDatabaseNameAlert = true
    }

    private func saveNewNameForSelectedDatabase() {
        defer { changedDatabaseName = "" }
        guard let selectedDatabase else { return }
        guard let updated = databases.update(name: changedDatabaseName, for: selectedDatabase) else {
            return
        }
        if database.file == selectedDatabase {
            // Update open database file
            database.file = updated
        }
    }

    private func toggleDefaultForSelectedDatabase() {
        guard let selectedDatabase else { return }
        defer { self.selectedDatabase = nil }
        databases.setAsDefault(database: selectedDatabase)
    }

    private func displayDocumentPicker() {
        showDocumentPicker = true
    }

    private func handle(result: Result<URL, Error>) {
        do {
            let selectedFile: URL = try result.get()
            if selectedFile.startAccessingSecurityScopedResource() {
                defer { selectedFile.stopAccessingSecurityScopedResource() }
                databases.importDatabase(at: selectedFile)
            } else {
                print("No access to file")
            }
        } catch {
            print("No file selected: \(error)")
        }
    }

    private func handlePicked(urls: [URL]) {
        print("Files picked.")
        for url in urls {
            databases.importDatabase(at: url)
        }
    }
}

#Preview {
    DatabasesTab(database: Database(), databases: .init())
}
