import BackgroundTasks
import ForgejoKit
import SwiftData
import SwiftUI
import UserNotifications

// MARK: - Settings Tab

struct SettingsTabView: View {
    @AppStorage("appearance") private var appearance: AppAppearance = .system
    @AppStorage("notificationsEnabled") private var notificationsEnabled = false
    @State private var authService: AuthenticationService
    @State private var showClearCacheConfirmation = false
    @State private var showClearCacheSuccess = false
    @Environment(\.modelContext) private var modelContext

    init(authService: AuthenticationService) {
        self.authService = authService
    }

    var body: some View {
        List {
            Section("Notifications") {
                Toggle("Push Notifications (Beta)", isOn: Binding(
                    get: { notificationsEnabled },
                    set: { newValue in
                        if newValue {
                            Task { await enableNotifications() }
                        } else {
                            Task { await disableNotifications() }
                        }
                    },
                ))
                .accessibilityIdentifier("notifications-toggle")
            }

            Section("Appearance") {
                Picker("Theme", selection: $appearance) {
                    Text("System").tag(AppAppearance.system)
                    Text("Light").tag(AppAppearance.light)
                    Text("Dark").tag(AppAppearance.dark)
                }
                .pickerStyle(.inline)
                .labelsHidden()
            }

            if let user = authService.currentUser {
                Section {
                    VStack(alignment: .leading, spacing: 8) {
                        Text(user.fullName ?? user.login)
                            .font(.headline)
                        Text("@\(user.login)")
                            .font(.subheadline)
                            .foregroundStyle(.secondary)
                        if let email = user.email {
                            Text(email)
                                .font(.caption)
                                .foregroundStyle(.secondary)
                        }
                    }
                    .padding(.vertical, 8)
                }
            }

            if let instance = authService.currentInstance {
                Section("Instance") {
                    LabeledContent("Server", value: instance.serverURL)
                    LabeledContent("User", value: instance.username)
                }
            }

            Section("Data") {
                Button {
                    showClearCacheConfirmation = true
                } label: {
                    Label("Clear Cache", systemImage: "trash")
                }
                .accessibilityIdentifier("clear-cache-button")
                .confirmationDialog("Clear Cache", isPresented: $showClearCacheConfirmation) {
                    Button("Clear Cache", role: .destructive) {
                        clearCache()
                    }
                } message: {
                    Text("This removes all cached data. Items will be fetched from the server on next load.")
                }
                .alert("Cache Cleared", isPresented: $showClearCacheSuccess) {
                    Button("OK") {}
                } message: {
                    Text("All cached data has been removed.")
                }
            }

            Section {
                Button {
                    authService.disconnect()
                } label: {
                    Label("Switch Instance", systemImage: "arrow.triangle.swap")
                }
                .accessibilityIdentifier("home-switch-instance-button")

                Button(role: .destructive) {
                    Task { await authService.logout(modelContext: modelContext) }
                } label: {
                    Label("Logout", systemImage: "rectangle.portrait.and.arrow.right")
                }
                .accessibilityIdentifier("home-logout-button")
            }

            AboutSection()
        }
        .navigationTitle("Settings")
    }

    private func clearCache() {
        DiskCache.removeAll()
        showClearCacheSuccess = true
    }

    private func enableNotifications() async {
        let center = UNUserNotificationCenter.current()
        do {
            let granted = try await center.requestAuthorization(options: [.alert, .sound, .badge])
            if granted {
                notificationsEnabled = true
                if let instance = authService.currentInstance {
                    let normalizedURL = ForgejoClient.normalizeServerURL(instance.serverURL)
                    if let client = authService.client {
                        let service = NotificationService(client: client)
                        let unread = try await service.fetchNotifications(statusTypes: ["unread"], page: 1, limit: 50)
                        let ids = Set(unread.map(\.id))
                        SeenNotificationStore().seed(ids: ids, for: normalizedURL, username: instance.username)
                    }
                }
                NotificationPollingService.shared.scheduleBackgroundPoll()
            } else {
                notificationsEnabled = false
            }
        } catch {
            notificationsEnabled = false
        }
    }
}

// MARK: - Merged Settings Tab

struct MergedSettingsTabView: View {
    @AppStorage("appearance") private var appearance: AppAppearance = .system
    @AppStorage("notificationsEnabled") private var notificationsEnabled = false
    @AppStorage("defaultAllInstances") private var defaultAllInstances = false
    @State private var showClearCacheConfirmation = false
    @State private var showClearCacheSuccess = false
    @Environment(\.modelContext) private var modelContext
    @Query private var allInstances: [ForgejoInstance]
    let manager: MultiInstanceManager
    var onDisconnect: (() -> Void)?

    var body: some View {
        List {
            Section("Notifications") {
                Toggle("Push Notifications (Beta)", isOn: Binding(
                    get: { notificationsEnabled },
                    set: { newValue in
                        if newValue {
                            Task { await enableNotifications() }
                        } else {
                            Task { await disableNotifications() }
                        }
                    },
                ))
                .accessibilityIdentifier("notifications-toggle")
            }

            Section("Appearance") {
                Picker("Theme", selection: $appearance) {
                    Text("System").tag(AppAppearance.system)
                    Text("Light").tag(AppAppearance.light)
                    Text("Dark").tag(AppAppearance.dark)
                }
                .pickerStyle(.inline)
                .labelsHidden()
            }

            Section("Connected Instances") {
                ForEach(manager.connections, id: \.instance.id) { connection in
                    VStack(alignment: .leading, spacing: 4) {
                        Text(manager.displayName(for: connection.instance))
                            .font(.headline)
                        Text(connection.instance.serverURL)
                            .font(.subheadline)
                            .foregroundStyle(.secondary)
                        Text("@\(connection.instance.username)")
                            .font(.caption)
                            .foregroundStyle(.secondary)
                    }
                    .padding(.vertical, 4)
                }
            }

            if !manager.failedInstances.isEmpty {
                Section("Failed Connections") {
                    ForEach(manager.failedInstances, id: \.instance.id) { failed in
                        VStack(alignment: .leading, spacing: 4) {
                            Text(manager.displayName(for: failed.instance))
                                .font(.headline)
                            Text(failed.error)
                                .font(.caption)
                                .foregroundStyle(.red)
                        }
                    }
                }
            }

            Section {
                Toggle("Default on Launch", isOn: $defaultAllInstances)
                    .onChange(of: defaultAllInstances) { _, isOn in
                        if isOn {
                            ForgejoInstance.clearDefaults(in: allInstances)
                            try? modelContext.save()
                        }
                    }
            } footer: {
                Text("Automatically connect to all instances when the app launches.")
                    .font(.caption)
            }

            Section("Data") {
                Button {
                    showClearCacheConfirmation = true
                } label: {
                    Label("Clear Cache", systemImage: "trash")
                }
                .accessibilityIdentifier("clear-cache-button")
                .confirmationDialog("Clear Cache", isPresented: $showClearCacheConfirmation) {
                    Button("Clear Cache", role: .destructive) {
                        clearCache()
                    }
                } message: {
                    Text("This removes all cached data. Items will be fetched from the server on next load.")
                }
                .alert("Cache Cleared", isPresented: $showClearCacheSuccess) {
                    Button("OK") {}
                } message: {
                    Text("All cached data has been removed.")
                }
            }

            Section {
                Button {
                    onDisconnect?()
                } label: {
                    Label("Switch Instance", systemImage: "arrow.triangle.swap")
                }
                .accessibilityIdentifier("home-switch-instance-button")
            }

            AboutSection()
        }
        .navigationTitle("Settings")
    }

    private func clearCache() {
        DiskCache.removeAll()
        showClearCacheSuccess = true
    }

    private func enableNotifications() async {
        let center = UNUserNotificationCenter.current()
        do {
            let granted = try await center.requestAuthorization(options: [.alert, .sound, .badge])
            if granted {
                notificationsEnabled = true
                for connection in manager.connections {
                    let instance = connection.instance
                    let normalizedURL = ForgejoClient.normalizeServerURL(instance.serverURL)
                    if let client = connection.authService.client {
                        let service = NotificationService(client: client)
                        let unread = try await service.fetchNotifications(statusTypes: ["unread"], page: 1, limit: 50)
                        let ids = Set(unread.map(\.id))
                        SeenNotificationStore().seed(ids: ids, for: normalizedURL, username: instance.username)
                    }
                }
                NotificationPollingService.shared.scheduleBackgroundPoll()
            } else {
                notificationsEnabled = false
            }
        } catch {
            notificationsEnabled = false
        }
    }
}

// MARK: - Disable Notifications

private func disableNotifications() async {
    UserDefaults.standard.set(false, forKey: "notificationsEnabled")
    await NotificationPollingService.shared.stopForegroundPolling()
    BGTaskScheduler.shared.cancel(taskRequestWithIdentifier: NotificationPollingService.backgroundTaskIdentifier)
    try? await UNUserNotificationCenter.current().setBadgeCount(0)
}

// MARK: - About Section

struct AboutSection: View {
    var body: some View {
        Section("About") {
            LabeledContent("Copyright", value: "Stefan Hausotte")

            VStack(alignment: .leading, spacing: 8) {
                Text("License")
                    .font(.subheadline)
                    .foregroundStyle(.secondary)
                // swiftlint:disable:next line_length
                Text("Forji is free software licensed under the GNU General Public License v3.0 or later (GPLv3+). You are free to use, modify, and redistribute it under the terms of that license.")
                    .font(.caption)
                    .foregroundStyle(.secondary)
            }
            .padding(.vertical, 4)

            VStack(alignment: .leading, spacing: 8) {
                Text("Logo")
                    .font(.subheadline)
                    .foregroundStyle(.secondary)
                Text("The Forji logo is based on the Forgejo logo by Caesar Schinas, licensed under CC BY-SA 4.0.")
                    .font(.caption)
                    .foregroundStyle(.secondary)
            }
            .padding(.vertical, 4)

            VStack(alignment: .leading, spacing: 8) {
                Text("Used Libraries")
                    .font(.subheadline)
                    .foregroundStyle(.secondary)
                VStack(alignment: .leading, spacing: 4) {
                    Link("ForgejoKit (MIT)", destination: URL(string: "https://codeberg.org/secana/ForgejoKit")!)
                    Link("Textual (MIT)", destination: URL(string: "https://github.com/gonzalezreal/textual")!)
                    Link(
                        "HighlightSwift (MIT)",
                        destination: URL(string: "https://github.com/appstefan/HighlightSwift")!,
                    )
                    Link(
                        "mermaid (MIT)",
                        destination: URL(string: "https://github.com/mermaid-js/mermaid")!,
                    )
                    Link(
                        "marked (MIT)",
                        destination: URL(string: "https://github.com/markedjs/marked")!,
                    )
                    Link(
                        "DOMPurify (Apache 2.0/MPL 2.0)",
                        destination: URL(string: "https://github.com/cure53/DOMPurify")!,
                    )
                    Link(
                        "github-markdown-css (MIT)",
                        destination: URL(string: "https://github.com/sindresorhus/github-markdown-css")!,
                    )
                }
                .font(.caption)
                .foregroundStyle(.secondary)
            }
            .padding(.vertical, 4)
        }
    }
}
