import SwiftUI
import Photos

// Spark Importer — a one-job helper. AFC drops image files into this app's
// Documents/inbox/ (via `afcclient --container com.petere.sparkimporter put …`);
// on launch/foreground the app imports each one into the camera roll through
// PhotoKit (PHAssetCreationRequest), which is the only mechanism that actually
// creates a Photos asset — AFC alone just writes bytes to a sandbox.
// Import-only: on success the source file is deleted so it isn't re-imported.

@main
struct SparkImporterApp: App {
    var body: some Scene {
        WindowGroup { ContentView() }
    }
}

struct ContentView: View {
    @State private var status = "Starting…"
    @State private var lines: [String] = []
    @State private var authed = false
    @State private var importing = false
    // Poll the inbox while foregrounded so drops import even without a fresh
    // launch (the driver may re-drop into an already-running app).
    private let poll = Timer.publish(every: 1.5, on: .main, in: .common).autoconnect()

    var body: some View {
        VStack(spacing: 14) {
            Text("Spark Importer").font(.title2.bold())
            Text(status)
                .font(.system(.body, design: .monospaced))
                .multilineTextAlignment(.center)
                .foregroundStyle(.secondary)
            Divider()
            ScrollView {
                VStack(alignment: .leading, spacing: 4) {
                    ForEach(lines.indices, id: \.self) { i in
                        Text(lines[i]).font(.system(.footnote, design: .monospaced))
                    }
                }.frame(maxWidth: .infinity, alignment: .leading)
            }
            Button("Import now") { requestAndImport() }
                .buttonStyle(.borderedProminent)
        }
        .padding()
        .onAppear { requestAndImport() }
        .onReceive(NotificationCenter.default.publisher(
            for: UIApplication.didBecomeActiveNotification)) { _ in requestAndImport() }
        .onReceive(poll) { _ in if authed { importInbox() } }
    }

    private var inboxURL: URL {
        FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0]
            .appendingPathComponent("inbox", isDirectory: true)
    }

    private func log(_ s: String) {
        DispatchQueue.main.async { lines.append(s) }
    }

    // Ask for add-only access (minimal scope; first launch shows one prompt),
    // then import. Subsequent launches skip the prompt once granted.
    private func requestAndImport() {
        PHPhotoLibrary.requestAuthorization(for: .addOnly) { st in
            DispatchQueue.main.async {
                switch st {
                case .authorized, .limited:
                    authed = true
                    status = "Photo access: granted — watching inbox"
                    importInbox()
                case .denied, .restricted:
                    status = "Photo access DENIED — enable in Settings › Photos"
                case .notDetermined:
                    status = "Waiting for permission…"
                @unknown default:
                    status = "Photo access: unknown (\(st.rawValue))"
                }
            }
        }
    }

    private func importInbox() {
        if importing { return }          // don't let overlapping ticks double-import
        let fm = FileManager.default
        try? fm.createDirectory(at: inboxURL, withIntermediateDirectories: true)
        let all = (try? fm.contentsOfDirectory(at: inboxURL,
                    includingPropertiesForKeys: nil)) ?? []
        let exts: Set<String> = ["jpg", "jpeg", "png", "heic", "heif"]
        let images = all.filter { exts.contains($0.pathExtension.lowercased()) }
                        .sorted { $0.lastPathComponent < $1.lastPathComponent }
        guard !images.isEmpty else {
            DispatchQueue.main.async { status = "inbox empty — waiting for drops" }
            return
        }
        importing = true
        DispatchQueue.main.async { status = "Importing \(images.count)…" }
        let group = DispatchGroup()
        var ok = 0
        for url in images {
            group.enter()
            PHPhotoLibrary.shared().performChanges {
                PHAssetCreationRequest.creationRequestForAssetFromImage(atFileURL: url)
            } completionHandler: { success, err in
                if success {
                    try? fm.removeItem(at: url)
                    ok += 1
                    log("✓ \(url.lastPathComponent)")
                } else {
                    log("✗ \(url.lastPathComponent): \(err?.localizedDescription ?? "unknown")")
                }
                group.leave()
            }
        }
        group.notify(queue: .main) {
            importing = false
            status = "Imported \(ok)/\(images.count) to camera roll"
        }
    }
}
