import Foundation
import Library
import SwiftUI

@MainActor
public struct ServiceLogView: View {
    @Environment(\.dismiss) private var dismiss

    @State private var isLoading = true
    @State private var content = ""
    @State private var alert: Alert?

    private let logFont = Font.system(.caption, design: .monospaced)

    public init() {}

    public var body: some View {
        viewBuilder {
            if isLoading {
                ProgressView().onAppear {
                    Task {
                        await loadContent()
                    }
                }
            } else {
                if content.isEmpty {
                    Text("Empty content")
                } else {
                    ScrollView {
                        Text(content)
                            .font(logFont)
                            .frame(maxWidth: .infinity, alignment: .topLeading)
                    }
                    .padding()
                }
            }
        }
        .toolbar {
            if !content.isEmpty {
                #if !os(tvOS)
                    ShareButtonCompat($alert) {
                        Label("Export", systemImage: "square.and.arrow.up.fill")
                    } itemURL: {
                        try content.generateShareFile(name: "service.log")
                    }
                #endif
                Button(role: .destructive) {
                    Task {
                        await deleteContent()
                    }
                } label: {
                    #if !os(tvOS)
                        Label("Delete", systemImage: "trash.fill")
                    #else
                        Image(systemName: "trash.fill")
                    #endif
                }
            }
        }
        .alertBinding($alert)
        .navigationTitle("Service Log")
        #if os(tvOS)
            .focusable()
        #endif
    }

    private nonisolated func loadContent() async {
        var content = ""
        do {
            content = try String(contentsOf: FilePath.cacheDirectory.appendingPathComponent("stderr.log"))
        } catch {}
        if content.isEmpty {
            do {
                content = try String(contentsOf: FilePath.cacheDirectory.appendingPathComponent("stderr.log.old"))
            } catch {}
        }
        #if DEBUG
            if content.isEmpty {
                content = "Empty content"
            }
        #endif
        if !content.isEmpty {
            var systemInfo = utsname()
            uname(&systemInfo)
            let machineMirror = Mirror(reflecting: systemInfo.machine)
            let machineName = machineMirror.children.reduce("") { identifier, element in
                guard let value = element.value as? Int8, value != 0 else { return identifier }
                return identifier + String(UnicodeScalar(UInt8(value)))
            }
            var deviceInfo = "Machine: " + machineName + "\n"
            #if os(iOS)
                await deviceInfo += "System: " + (UIDevice.current.systemName) + " " + (UIDevice.current.systemVersion) + "\n"
            #elseif os(macOS)
                deviceInfo += "System: macOS " + ProcessInfo().operatingSystemVersionString + "\n"
            #endif
            content = deviceInfo + "\n" + content
        }
        await MainActor.run { [content] in
            self.content = content
            isLoading = false
        }
    }

    private nonisolated func deleteContent() async {
        try? FileManager.default.removeItem(at: FilePath.cacheDirectory.appendingPathComponent("stderr.log"))
        try? FileManager.default.removeItem(at: FilePath.cacheDirectory.appendingPathComponent("stderr.log.old"))
        await MainActor.run {
            dismiss()
            isLoading = true
        }
    }
}
