//
//  ContentView.swift
//  Ventry Upload Watcher
//
//  Created by Jan-Marlon Leibl on 18.01.25.
//

import SwiftUI
import AppKit
import UserNotifications
import ServiceManagement
import CoreServices

extension NSWindow {
    open override func awakeFromNib() {
        super.awakeFromNib()
        self.styleMask.remove(.resizable)
        self.styleMask.remove(.fullScreen)
    }
}

extension Color {
    static let accentPurple = Color(hex: 0x8331FD)
}

extension Color {
    init(hex: UInt) {
        self.init(
            .sRGB,
            red: Double((hex >> 16) & 0xff) / 255,
            green: Double((hex >> 8) & 0xff) / 255,
            blue: Double(hex & 0xff) / 255,
            opacity: 1
        )
    }
}

// MARK: - Upload Manager
class UploadManager {
    private static let endpoint = URL(string: "https://ventry.host/api/upload")!
    
    static func uploadFile(_ fileURL: URL, apiKey: String, completion: @escaping (Result<String, Error>) -> Void) {
        var request = URLRequest(url: endpoint)
        request.httpMethod = "POST"
        request.setValue(apiKey, forHTTPHeaderField: "Authorization")
        let boundary = "Boundary-\(UUID().uuidString)"
        request.setValue("multipart/form-data; boundary=\(boundary)", forHTTPHeaderField: "Content-Type")
        
        URLSession.shared.uploadTask(with: request, from: createMultipartFormData(fileURL: fileURL, boundary: boundary)) { data, response, error in
            if let error = error { return completion(.failure(error)) }
            guard let httpResponse = response as? HTTPURLResponse,
                  (200...299).contains(httpResponse.statusCode),
                  let data = data,
                  let responseString = String(data: data, encoding: .utf8) else {
                return completion(.failure(NSError(domain: "", code: (response as? HTTPURLResponse)?.statusCode ?? -1)))
            }
            completion(.success(responseString))
        }.resume()
    }
    
    private static func createMultipartFormData(fileURL: URL, boundary: String) -> Data {
        var data = Data()
        let filename = fileURL.lastPathComponent.replacingOccurrences(of: " ", with: "%20")
        data.append("--\(boundary)\r\nContent-Disposition: form-data; name=\"file\"; filename=\"\(filename)\"\r\nContent-Type: \(fileURL.mimeType())\r\n\r\n".data(using: .utf8)!)
        if let fileData = try? Data(contentsOf: fileURL) {
            data.append(fileData)
            data.append("\r\n--\(boundary)--\r\n".data(using: .utf8)!)
        }
        return data
    }
}

extension URL {
    func mimeType() -> String {
        let mimeTypes = ["jpg": "image/jpeg", "jpeg": "image/jpeg", "png": "image/png",
                        "gif": "image/gif", "webp": "image/webp", "mp4": "video/mp4",
                        "mov": "video/quicktime"]
        return mimeTypes[pathExtension.lowercased()] ?? "application/octet-stream"
    }
}

// MARK: - Folder Monitor
class FolderMonitor: ObservableObject {
    @Published private(set) var isWatching = false
    private var timer: Timer?
    private var currentPaths: [String] = []
    private var knownFiles = Set<String>()
    var onFileDetected: ((URL) -> Void)?
    
    deinit { stopWatching() }
    
    func startWatching(paths: [String]) {
        stopWatching()
        currentPaths = paths
        for path in paths {
            let url = URL(fileURLWithPath: path)
            guard url.startAccessingSecurityScopedResource() else {
                NotificationManager.send(title: "Permission Required", message: "Please grant folder access")
                continue
            }
            saveBookmark(for: url)
        }
        updateKnownFiles()
        startMonitoring()
    }
    
    private func startMonitoring() {
        timer = Timer.scheduledTimer(withTimeInterval: 1.0, repeats: true) { [weak self] _ in
            self?.checkForNewFiles()
        }
        isWatching = true
    }
    
    private func checkForNewFiles() {
        for path in currentPaths {
            do {
                let contents = try FileManager.default.contentsOfDirectory(atPath: path)
                let newFiles = Set(contents).subtracting(knownFiles)
                
                for file in newFiles {
                    let fileURL = URL(fileURLWithPath: path).appendingPathComponent(file)
                    if fileURL.lastPathModified.timeIntervalSinceNow > -2 {
                        onFileDetected?(fileURL)
                    }
                }
                
                knownFiles = knownFiles.union(newFiles)
            } catch {
                print("Error checking files in \(path): \(error)")
            }
        }
    }
    
    private func updateKnownFiles() {
        var allFiles = Set<String>()
        for path in currentPaths {
            guard let contents = try? FileManager.default.contentsOfDirectory(atPath: path) else { continue }
            allFiles = allFiles.union(Set(contents.map { path + "/" + $0 }))
        }
        knownFiles = allFiles
    }
    
    private func saveBookmark(for url: URL) {
        guard let bookmarkData = try? url.bookmarkData(
            options: .withSecurityScope,
            includingResourceValuesForKeys: nil,
            relativeTo: nil
        ) else { return }
        
        UserDefaults.standard.set(bookmarkData, forKey: "FolderBookmark-\(url.path)")
    }
    
    func stopWatching() {
        timer?.invalidate()
        timer = nil
        isWatching = false
        currentPaths.removeAll()
        knownFiles.removeAll()
    }
    
    func addPath(_ path: String) {
        if !currentPaths.contains(path) {
            currentPaths.append(path)
            let url = URL(fileURLWithPath: path)
            guard url.startAccessingSecurityScopedResource() else {
                NotificationManager.send(title: "Permission Required", message: "Please grant folder access")
                return
            }
            saveBookmark(for: url)
            updateKnownFiles()
        }
    }
}

// MARK: - Notification Manager
class NotificationManager {
    static func send(title: String, message: String) {
        let content = UNMutableNotificationContent()
        content.title = title
        content.body = message
        content.sound = .default
        UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .sound]) { granted, _ in
            if granted {
                UNUserNotificationCenter.current().add(UNNotificationRequest(identifier: UUID().uuidString,
                                                                          content: content, trigger: nil))
            }
        }
    }
}

// MARK: - Haptics
class HapticManager {
    static func play(_ type: NSHapticFeedbackManager.FeedbackPattern) {
        NSHapticFeedbackManager.defaultPerformer.perform(type, performanceTime: .default)
    }
    
    static func success() { play(.levelChange) }
    static func error() { play(.generic) }
    static func tap() { play(.alignment) }
}

// MARK: - Views
struct CardView<Content: View>: View {
    let content: Content
    
    init(@ViewBuilder content: () -> Content) {
        self.content = content()
    }
    
    var body: some View {
        content
            .padding()
            .background(Color(.windowBackgroundColor))
            .cornerRadius(12)
    }
}

struct StatusBadge: View {
    let status: String
    let color: Color
    
    var body: some View {
        Text(status)
            .font(.caption.bold())
            .padding(.horizontal, 8)
            .padding(.vertical, 4)
            .background(color.opacity(0.2))
            .foregroundColor(color)
            .cornerRadius(6)
    }
}

class LaunchAtLoginHelper {
    static func setLaunchAtLogin(_ enabled: Bool) {
        let service = SMAppService.mainApp
        do {
            if enabled {
                try service.register()
            } else {
                try service.unregister()
            }
            print("Successfully \(enabled ? "enabled" : "disabled") launch at login")
        } catch {
            print("Failed to \(enabled ? "enable" : "disable") launch at login: \(error)")
        }
    }
}

struct SettingsView: View {
    @Binding var isPresented: Bool
    @Binding var apiKey: String
    @Environment(\.colorScheme) var colorScheme
    @FocusState private var isAPIKeyFocused: Bool
    @AppStorage("launchAtLogin") private var launchAtLogin = false
    
    var body: some View {
        VStack(spacing: Design.padding) {
            HStack {
                Text("Settings")
                    .font(.system(size: 24, weight: .bold))
                Spacer()
                Button(action: { 
                    withAnimation(Animation.spring) {
                        isPresented = false
                    }
                }) {
                    Circle()
                        .fill(Color(.windowBackgroundColor).opacity(0.8))
                        .frame(width: 32, height: 32)
                        .overlay(
                            Image(systemName: "xmark")
                                .font(.system(size: 12, weight: .medium))
                                .foregroundColor(.secondary)
                        )
                }
                .buttonStyle(.plain)
            }
            
            VStack(alignment: .leading, spacing: Design.spacing) {
                Text("API Key")
                    .font(.system(size: 15, weight: .semibold))
                
                SecureField("Enter your ventry.host API key", text: $apiKey)
                    .textFieldStyle(.plain)
                    .padding(12)
                    .background(
                        RoundedRectangle(cornerRadius: Design.cornerRadius, style: .continuous)
                            .fill(Color(.textBackgroundColor))
                    )
                    .focused($isAPIKeyFocused)
                
                Text("Get your API key from ventry.host")
                    .font(.system(size: 12))
                    .foregroundColor(.secondary)
            }
            .padding(.bottom, 8)
            
            VStack(alignment: .leading, spacing: Design.spacing) {
                Text("Startup Options")
                    .font(.system(size: 15, weight: .semibold))
                    .padding(.bottom, 4)
                
                Toggle(isOn: $launchAtLogin) {
                    VStack(alignment: .leading, spacing: 2) {
                        Text("Launch at login")
                            .font(.system(size: 14))
                        Text("Automatically start the app when you log in")
                            .font(.system(size: 12))
                .foregroundColor(.secondary)
                    }
                }
                .onChange(of: launchAtLogin) { _, newValue in
                    LaunchAtLoginHelper.setLaunchAtLogin(newValue)
                }
            }
            
            Spacer()
            
            Button(action: { 
                HapticManager.success()
                withAnimation(Animation.spring) {
                    isPresented = false
                }
            }) {
                Text("Save")
                    .font(.system(size: 15, weight: .semibold))
                    .foregroundColor(.white)
                    .frame(maxWidth: .infinity)
                    .padding(.vertical, 12)
                    .background(
                        RoundedRectangle(cornerRadius: Design.cornerRadius, style: .continuous)
                            .fill(Color.accentPurple)
                    )
            }
            .buttonStyle(.plain)
            .keyboardShortcut(.return)
        }
        .padding(24)
        .frame(width: 400, height: 360)
        .background(colorScheme == .dark ? Color(.windowBackgroundColor) : .white)
        .onAppear { isAPIKeyFocused = true }
    }
}

@propertyWrapper
struct UserDefaultsArray<T: Codable> {
    private let key: String
    
    init(key: String) {
        self.key = key
    }
    
    var wrappedValue: [T] {
        get {
            guard let data = UserDefaults.standard.data(forKey: key),
                  let array = try? JSONDecoder().decode([T].self, from: data) else {
                return []
            }
            return array
        }
        set {
            guard let data = try? JSONEncoder().encode(newValue) else { return }
            UserDefaults.standard.set(data, forKey: key)
        }
    }
}

struct HeaderView: View {
    @Binding var showingSettings: Bool
    
    var body: some View {
        HStack(spacing: Design.padding) {
            VStack(alignment: .leading, spacing: 2) {
                Text("ventry.host")
                    .font(.system(size: 24, weight: .bold))
                Text("Tool for uploading files to ventry.host")
                    .font(.system(size: 13, weight: .medium))
                    .foregroundColor(.secondary)
            }
            
            Spacer()
            
            Button(action: {
                HapticManager.tap()
                withAnimation(Animation.spring) {
                    showingSettings.toggle()
                }
            }) {
                Image(systemName: "gear")
                    .font(.system(size: Design.iconSize))
                    .foregroundColor(.secondary)
                    .frame(width: 32, height: 32)
                    .background(Color(.controlBackgroundColor))
                    .clipShape(Circle())
            }
            .buttonStyle(.plain)
        }
    }
}

struct StatusCardView: View {
    let folderMonitor: FolderMonitor
    let uploadStatus: String
    let lastUpload: String
    
    var body: some View {
        VStack(spacing: Design.padding) {
                HStack {
                ZStack {
                    Circle()
                        .fill(folderMonitor.isWatching ? Color.green.opacity(0.15) : Color.red.opacity(0.15))
                        .frame(width: 24, height: 24)
                    
                    Circle()
                        .fill(folderMonitor.isWatching ? Color.green : Color.red)
                        .frame(width: 8, height: 8)
                        .blur(radius: folderMonitor.isWatching ? 2 : 0)
                }
                
                Text(folderMonitor.isWatching ? "Watching" : "Inactive")
                    .font(.system(size: Design.iconSize, weight: .medium))
                    .foregroundColor(folderMonitor.isWatching ? .green : .red)
                Spacer()
            }
            
            VStack(spacing: Design.spacing) {
                statusRow(
                    icon: "arrow.up.circle",
                    title: "Status",
                    value: uploadStatus
                )
                
                Divider()
                    .background(Color.primary.opacity(Design.opacity))
                
                statusRow(
                    icon: "clock",
                    title: "Last Upload",
                    value: lastUpload
                )
            }
        }
        .padding(Design.padding)
        .background(Color(.controlBackgroundColor))
        .cornerRadius(Design.cornerRadius)
        .animation(Animation.spring, value: folderMonitor.isWatching)
    }
    
    private func statusRow(icon: String, title: String, value: String) -> some View {
        HStack(spacing: Design.spacing) {
            Image(systemName: icon)
                .font(.system(size: Design.iconSize))
                .foregroundColor(.secondary)
                .frame(width: 16)
            
            Text(title)
                .font(.system(size: Design.iconSize))
                .foregroundColor(.secondary)
            
            Spacer()
            
            Text(value)
                .font(.system(size: Design.iconSize, weight: .medium))
                .multilineTextAlignment(.trailing)
        }
    }
}

struct WatchedFoldersView: View {
    @Binding var watchedFolders: [String]
    let folderMonitor: FolderMonitor
    let onAddFolder: () -> Void
    let onStopWatching: () -> Void
    
    var body: some View {
        VStack(spacing: Design.spacing) {
            List {
                ForEach(watchedFolders, id: \.self) { path in
                    folderCard(path)
                        .listRowInsets(EdgeInsets(top: 4, leading: 0, bottom: 4, trailing: 0))
                        .listRowBackground(Color.clear)
                        .listRowSeparator(.hidden)
                        .swipeActions(edge: .trailing, allowsFullSwipe: true) {
                            Button(role: .destructive) {
                                withAnimation(Animation.spring) {
                                    watchedFolders.removeAll { $0 == path }
                                    if watchedFolders.isEmpty {
                                        folderMonitor.stopWatching()
                                    } else {
                                        folderMonitor.startWatching(paths: watchedFolders)
                                    }
                                }
                                HapticManager.tap()
                            } label: {
                                Label("Remove", systemImage: "trash")
                            }
                        }
                }
            }
            .listStyle(.plain)
            .scrollContentBackground(.hidden)
            .frame(height: CGFloat(watchedFolders.count * 60))
            .padding(.horizontal, -8)
            
            VStack(spacing: Design.spacing) {
                Button(action: {
                    HapticManager.tap()
                    onAddFolder()
                }) {
                    HStack(spacing: Design.spacing) {
                        Image(systemName: "folder.badge.plus")
                            .font(.system(size: Design.iconSize))
                        Text("Add Another Folder")
                            .font(.system(size: Design.iconSize))
                    }
                    .frame(maxWidth: .infinity)
                    .padding(12)
                    .background(
                        RoundedRectangle(cornerRadius: Design.cornerRadius)
                            .fill(Color.accentPurple.opacity(Design.opacity))
                    )
                    .foregroundColor(.accentPurple)
                }
                .buttonStyle(.plain)
                
                Button(action: {
                    HapticManager.tap()
                    onStopWatching()
                }) {
                    HStack(spacing: Design.spacing) {
                        Image(systemName: "stop.circle.fill")
                            .font(.system(size: Design.iconSize))
                        Text("Stop Watching")
                            .font(.system(size: Design.iconSize))
                    }
                    .frame(maxWidth: .infinity)
                    .padding(12)
                    .background(
                        RoundedRectangle(cornerRadius: Design.cornerRadius)
                            .fill(Color.red.opacity(Design.opacity))
                    )
                    .foregroundColor(.red)
                }
                .buttonStyle(.plain)
            }
        }
    }
    
    private func folderCard(_ path: String) -> some View {
        HStack(spacing: Design.spacing) {
            Image(systemName: "folder.fill")
                .font(.system(size: Design.iconSize))
                .foregroundColor(.accentPurple)
            
            Text(path)
                .font(.system(size: Design.iconSize))
                .lineLimit(1)
                .truncationMode(.middle)
                .frame(maxWidth: .infinity, alignment: .leading)
        }
        .padding(.vertical, 12)
        .padding(.horizontal, Design.padding)
        .frame(maxWidth: .infinity)
        .background(
            RoundedRectangle(cornerRadius: Design.cornerRadius, style: .continuous)
                .fill(Color.accentPurple.opacity(Design.opacity))
        )
        .transition(.move(edge: .bottom).combined(with: .opacity))
    }
}

struct LeftSideView: View {
    let folderMonitor: FolderMonitor
    let uploadStatus: String
    let lastUpload: String
    @Binding var showingSettings: Bool
    @Binding var watchedFolders: [String]
    let apiKey: String
    let onToggleWatching: () -> Void
    let onAddFolder: () -> Void
    
    var body: some View {
        ScrollView {
            VStack(spacing: 16) {
                HeaderView(showingSettings: $showingSettings)
                StatusCardView(folderMonitor: folderMonitor, uploadStatus: uploadStatus, lastUpload: lastUpload)
                
                if !watchedFolders.isEmpty {
                    WatchedFoldersView(
                        watchedFolders: $watchedFolders,
                        folderMonitor: folderMonitor,
                        onAddFolder: onAddFolder,
                        onStopWatching: onToggleWatching
                    )
                }
                
                if watchedFolders.isEmpty {
                    ActionButtonView(folderMonitor: folderMonitor, apiKey: apiKey, onToggleWatching: onToggleWatching)
                }
                
                Spacer(minLength: 0)
            }
            .padding(24)
        }
        .frame(width: 360)
        .background(Color(.windowBackgroundColor))
    }
}

struct RightSideView: View {
    let isUploading: Bool
    @Binding var uploadHistory: [(date: Date, url: String, filePath: String)]
    @Binding var copiedURL: String?
    let folderMonitor: FolderMonitor
    
    var body: some View {
        VStack(alignment: .leading, spacing: 16) {
            Text("Recent Uploads")
                .font(.system(size: 20, weight: .bold))
            
            if isUploading {
                UploadingCardView()
            }
            
            UploadHistoryListView(
                uploadHistory: $uploadHistory,
                copiedURL: $copiedURL,
                folderMonitor: folderMonitor
            )
        }
        .padding(24)
        .frame(maxWidth: .infinity)
        .background(Color(.textBackgroundColor))
    }
}

struct ActionButtonView: View {
    let folderMonitor: FolderMonitor
    let apiKey: String
    let onToggleWatching: () -> Void
    
    var body: some View {
        Button(action: {
            HapticManager.tap()
            onToggleWatching()
        }) {
            HStack(spacing: 8) {
                Image(systemName: folderMonitor.isWatching ? "stop.circle.fill" : "folder.badge.plus")
                Text(folderMonitor.isWatching ? "Stop Watching" : "Add Folders...")
                    .font(.system(size: 15, weight: .semibold))
            }
            .frame(maxWidth: .infinity)
            .frame(height: 44)
            .background(folderMonitor.isWatching ? Color.red : Color(.controlAccentColor))
            .cornerRadius(12)
            .foregroundColor(.white)
        }
        .buttonStyle(.plain)
        .disabled(apiKey.isEmpty)
        .opacity(apiKey.isEmpty ? 0.5 : 1)
        .help(folderMonitor.isWatching ? "Stop watching all folders" : "Select multiple folders to watch")
    }
}

struct UploadingCardView: View {
    var body: some View {
        HStack(spacing: 12) {
            ProgressView()
                .scaleEffect(0.8)
            Text("Uploading file...")
                .font(.system(size: 14, weight: .medium))
            Spacer()
        }
        .padding(16)
        .background(
            ZStack {
                RoundedRectangle(cornerRadius: 16, style: .continuous)
                    .fill(Color.accentPurple.opacity(0.1))
                
                RoundedRectangle(cornerRadius: 16, style: .continuous)
                    .fill(
                        LinearGradient(
                            colors: [Color.accentPurple.opacity(0.1), Color.clear],
                            startPoint: .topLeading,
                            endPoint: .bottomTrailing
                        )
                    )
            }
        )
        .transition(.move(edge: .top).combined(with: .opacity))
    }
}

private enum Animation {
    static let spring = SwiftUI.Animation.spring(response: 0.3, dampingFraction: 0.7)
    static let copyDelay: TimeInterval = 1.5
}

private enum Design {
    static let cornerRadius: CGFloat = 12
    static let opacity = 0.1
    static let iconSize: CGFloat = 14
    static let spacing: CGFloat = 8
    static let padding: CGFloat = 16
}

struct UploadHistoryListView: View {
    @Binding var uploadHistory: [(date: Date, url: String, filePath: String)]
    @Binding var copiedURL: String?
    let folderMonitor: FolderMonitor
    @Namespace private var scrollSpace
    
    var body: some View {
        ScrollViewReader { proxy in
            List {
                ForEach(uploadHistory, id: \.date) { upload in
                    lastUploadCard(upload.url, date: upload.date, filePath: upload.filePath)
                        .listRowInsets(EdgeInsets(top: 4, leading: 0, bottom: 4, trailing: 0))
                        .listRowBackground(Color.clear)
                        .listRowSeparator(.hidden)
                        .swipeActions(edge: .trailing, allowsFullSwipe: false) {
                            Button(role: .destructive) {
                                withAnimation(Animation.spring) {
                                    uploadHistory.removeAll { $0.url == upload.url }
                                }
                                HapticManager.tap()
                            } label: {
                                Label("Delete", systemImage: "trash")
                            }
                            
                            Button {
                                if let url = URL(string: upload.url) {
                                    NSWorkspace.shared.open(url)
                                    HapticManager.tap()
                                }
                            } label: {
                                Label("Open", systemImage: "safari")
                            }
                            .tint(.accentPurple)
                        }
                        .id(upload.date)
                }
                
                if uploadHistory.isEmpty && !folderMonitor.isWatching {
                    VStack(spacing: Design.spacing) {
                        Image(systemName: "folder.badge.plus")
                            .font(.system(size: 32))
                            .foregroundColor(.secondary)
                        Text("Select a folder to start watching")
                            .font(.system(size: Design.iconSize))
                            .foregroundColor(.secondary)
                    }
                    .frame(maxWidth: .infinity)
                    .frame(height: 160)
                    .listRowInsets(EdgeInsets())
                    .listRowBackground(Color.clear)
                    .listRowSeparator(.hidden)
                }
            }
            .listStyle(.plain)
            .scrollContentBackground(.hidden)
            .onChange(of: uploadHistory.map(\.url)) { oldValue, newValue in
                if !newValue.isEmpty {
                    withAnimation(Animation.spring) {
                        proxy.scrollTo(uploadHistory[0].date, anchor: .top)
                    }
                }
            }
        }
    }
    
    private func lastUploadCard(_ url: String, date: Date = Date(), filePath: String? = nil) -> some View {
        Button(action: {
            copyToClipboard(url)
            withAnimation(Animation.spring) {
                copiedURL = url
            }
            HapticManager.success()
            DispatchQueue.main.asyncAfter(deadline: .now() + Animation.copyDelay) {
                withAnimation(Animation.spring) {
                    if copiedURL == url {
                        copiedURL = nil
                    }
                }
            }
        }) {
            VStack(alignment: .leading, spacing: Design.spacing) {
                if let filePath = filePath,
                   let nsImage = NSImage(contentsOf: URL(fileURLWithPath: filePath)) {
                    Image(nsImage: nsImage)
                        .resizable()
                        .aspectRatio(contentMode: .fill)
                        .frame(height: 120)
                        .frame(maxWidth: .infinity)
                        .clipShape(RoundedRectangle(cornerRadius: Design.cornerRadius))
                }
                
                VStack(alignment: .leading, spacing: Design.spacing) {
                    Text(date.formatted(date: .numeric, time: .shortened))
                        .font(.system(size: 12))
                .foregroundColor(.secondary)
                    
                    HStack(spacing: Design.spacing) {
                        Image(systemName: "link")
                            .font(.system(size: Design.iconSize))
                            .foregroundColor(copiedURL == url ? .green : .accentPurple)
                        
                        Text(url)
                            .font(.system(size: Design.iconSize))
                            .lineLimit(1)
                            .truncationMode(.middle)
                        
                        Spacer()
                        
                        HStack(spacing: 4) {
                            if copiedURL == url {
                                Image(systemName: "checkmark.circle.fill")
                                    .font(.system(size: Design.iconSize))
                                    .transition(.scale.combined(with: .opacity))
                                Text("Copied!")
                            } else {
                                Text("Copy")
                            }
                        }
                        .font(.system(size: 12, weight: .medium))
                        .foregroundColor(copiedURL == url ? .green : .accentPurple)
                        .animation(Animation.spring, value: copiedURL)
                    }
                }
            }
            .padding(Design.padding)
            .background(
                RoundedRectangle(cornerRadius: Design.cornerRadius, style: .continuous)
                    .fill(copiedURL == url ? Color.green.opacity(Design.opacity) : Color.accentPurple.opacity(Design.opacity))
            )
        }
        .buttonStyle(.plain)
        .contentShape(Rectangle())
        .animation(Animation.spring, value: copiedURL)
    }
    
    private func copyToClipboard(_ text: String) {
        NSPasteboard.general.clearContents()
        NSPasteboard.general.setString(text, forType: .string)
    }
}

class WindowManager {
    static let shared = WindowManager()
    private var window: NSWindow?
    
    func setWindow(_ window: NSWindow?) {
        self.window = window
    }
    
    func hideWindow() {
        window?.orderOut(nil)
    }
    
    func showWindow() {
        window?.makeKeyAndOrderFront(nil)
        NSApp.activate(ignoringOtherApps: true)
    }
}

struct ContentView: View {
    @StateObject private var folderMonitor = FolderMonitor()
    @State private var uploadStatus = "No active uploads"
    @State private var lastUpload = "Never"
    @State private var showingSettings = false
    @AppStorage("apiKey") private var apiKey = ""
    @State private var watchedFolders: [String] = UserDefaults.standard.stringArray(forKey: "watchedFolders") ?? []
    @State private var errorMessage: String?
    @State private var showError = false
    @State private var lastUploadURL: String?
    @State private var isUploading = false
    @State private var showCopiedBadge = false
    @Environment(\.colorScheme) var colorScheme
    @State private var uploadHistory: [(date: Date, url: String, filePath: String)] = []
    @State private var copiedURL: String? = nil
    
    var body: some View {
        MainLayout {
            HStack(spacing: 0) {
                LeftSideView(
                    folderMonitor: folderMonitor,
                    uploadStatus: uploadStatus,
                    lastUpload: lastUpload,
                    showingSettings: $showingSettings,
                    watchedFolders: $watchedFolders,
                    apiKey: apiKey,
                    onToggleWatching: toggleWatching,
                    onAddFolder: selectFolder
                )
                
                RightSideView(
                    isUploading: isUploading,
                    uploadHistory: $uploadHistory,
                    copiedURL: $copiedURL,
                    folderMonitor: folderMonitor
                )
            }
        }
        .frame(width: 800, height: 400)
        .background(Color(.windowBackgroundColor))
        .alert("Error", isPresented: $showError) {
            Button("OK", role: .cancel) {}
        } message: {
            Text(errorMessage ?? "Unknown error")
        }
        .sheet(isPresented: $showingSettings) {
            SettingsView(isPresented: $showingSettings, apiKey: $apiKey)
        }
        .onAppear {
            setupFolderMonitor()
            restoreWatching()
        }
        .onChange(of: watchedFolders) { oldValue, newValue in
            UserDefaults.standard.set(newValue, forKey: "watchedFolders")
            if !folderMonitor.isWatching && !newValue.isEmpty {
                folderMonitor.startWatching(paths: newValue)
            }
        }
    }
    
    private func toggleWatching() {
        if folderMonitor.isWatching {
            folderMonitor.stopWatching()
            uploadStatus = "Watching stopped"
            watchedFolders.removeAll()
        } else {
            selectFolder()
        }
    }
    
    private func selectFolder() {
        let panel = NSOpenPanel()
        panel.allowsMultipleSelection = true
        panel.canChooseDirectories = true
        panel.canChooseFiles = false
        panel.message = "Select folders to watch for screenshots"
        panel.prompt = "Watch Folders"
        
        panel.begin { response in
            guard response == .OK else { return }
            
            DispatchQueue.main.async {
                for url in panel.urls {
                    guard url.startAccessingSecurityScopedResource() else {
                        NotificationManager.send(title: "Permission Required", message: "Please grant folder access for \(url.path)")
                        continue
                    }
                    
                    if !watchedFolders.contains(url.path) {
                        watchedFolders.append(url.path)
                        
                        if let bookmarkData = try? url.bookmarkData(options: .withSecurityScope) {
                            UserDefaults.standard.set(bookmarkData, forKey: "FolderBookmark-\(url.path)")
                        }
                    }
                }
                
                if !watchedFolders.isEmpty {
                    if !folderMonitor.isWatching {
                        uploadStatus = "Starting to watch folders..."
                        folderMonitor.startWatching(paths: watchedFolders)
                    } else {
                        for url in panel.urls {
                            folderMonitor.addPath(url.path)
                        }
                    }
                    
                    uploadStatus = "Watching for new files..."
                    NotificationManager.send(title: "Folders Added", message: "Now watching \(panel.urls.count) new folder(s)")
                }
            }
        }
    }
    
    private func setupFolderMonitor() {
        folderMonitor.onFileDetected = handleNewFile
    }
    
    private func handleNewFile(_ fileURL: URL) {
        uploadStatus = "Uploading \(fileURL.lastPathComponent)..."
        NotificationManager.send(title: "Uploading File", message: "Starting upload of \(fileURL.lastPathComponent)")
        withAnimation { isUploading = true }
        
        UploadManager.uploadFile(fileURL, apiKey: apiKey) { result in
            DispatchQueue.main.async { 
                withAnimation { isUploading = false }
                handleUploadResult(result)
            }
        }
    }
    
    private func handleUploadResult(_ result: Result<String, Error>) {
        switch result {
        case .success(let response): handleSuccessfulUpload(response)
        case .failure(let error): handleFailedUpload(error)
        }
    }
    
    private func handleSuccessfulUpload(_ response: String) {
        do {
            if let jsonData = response.data(using: .utf8),
               let json = try JSONSerialization.jsonObject(with: jsonData) as? [String: Any],
               let url = json["url"] as? String,
               let currentFile = lastUploadedFile?.path {
                withAnimation(.spring()) {
                    uploadStatus = "Upload successful"
                    lastUpload = Date().formatted(date: .numeric, time: .shortened)
                    lastUploadURL = url
                    uploadHistory.insert((date: Date(), url: url, filePath: currentFile), at: 0)
                    if uploadHistory.count > 50 {
                        uploadHistory.removeLast()
                    }
                }
                copyToClipboard(url)
                HapticManager.success()
                NotificationManager.send(title: "Upload Successful", message: "URL copied to clipboard")
            } else {
                throw NSError(domain: "", code: -1)
            }
        } catch {
            handleFailedUpload(error)
        }
    }
    
    private func handleFailedUpload(_ error: Error) {
        withAnimation {
            errorMessage = error.localizedDescription
            showError = true
            uploadStatus = "Upload failed"
        }
        HapticManager.error()
        NotificationManager.send(title: "Upload Failed", message: error.localizedDescription)
    }
    
    private var lastUploadedFile: URL? {
        guard let path = watchedFolders.first else { return nil }
        let fm = FileManager.default
        let contents = try? fm.contentsOfDirectory(atPath: path)
        return contents?.compactMap { URL(fileURLWithPath: path).appendingPathComponent($0) }
            .sorted { $0.lastPathModified > $1.lastPathModified }
            .first
    }
    
    private func copyToClipboard(_ text: String) {
        NSPasteboard.general.clearContents()
        NSPasteboard.general.setString(text, forType: .string)
        uploadStatus = "URL copied to clipboard"
    }
    
    private func restoreWatching() {
        guard !apiKey.isEmpty else { return }
        
        var validPaths: [String] = []
        
        for path in watchedFolders {
            guard FileManager.default.fileExists(atPath: path),
                  let bookmarkData = UserDefaults.standard.data(forKey: "FolderBookmark-\(path)") else { continue }
            
            var isStale = false
            do {
                let url = try URL(resolvingBookmarkData: bookmarkData,
                                options: .withSecurityScope,
                                relativeTo: nil,
                                bookmarkDataIsStale: &isStale)
                
                guard url.startAccessingSecurityScopedResource() else {
                    print("Failed to access security scoped resource for path: \(path)")
                    continue
                }
                
                validPaths.append(url.path)
            } catch {
                print("Failed to resolve bookmark for path: \(path), error: \(error)")
            }
        }
        
        if !validPaths.isEmpty {
            DispatchQueue.main.async {
                watchedFolders = validPaths
                folderMonitor.startWatching(paths: validPaths)
                uploadStatus = "Watching for new files..."
                NotificationManager.send(title: "Ventry Upload Watcher", message: "Resumed watching \(validPaths.count) folder(s)")
            }
        }
    }
}

struct MainLayout<Content: View>: View {
    let content: Content
    @Environment(\.colorScheme) var colorScheme
    
    init(@ViewBuilder content: () -> Content) {
        self.content = content()
    }
    
    var body: some View {
        ZStack {
            Color(colorScheme == .dark ? .windowBackgroundColor : .white)
                .ignoresSafeArea()
            content
        }
    }
}

#Preview {
    ContentView()
}

extension URL {
    var lastPathModified: Date {
        (try? resourceValues(forKeys: [.contentModificationDateKey]))?.contentModificationDate ?? Date.distantPast
    }
}

class AppDelegate: NSObject, NSApplicationDelegate {
    var statusItem: NSStatusItem?
    
    func applicationDidFinishLaunching(_ notification: Notification) {
        setupStatusItem()
        
        if let window = NSApplication.shared.windows.first {
            WindowManager.shared.setWindow(window)
        }
    }
    
    private func setupStatusItem() {
        statusItem = NSStatusBar.system.statusItem(withLength: NSStatusItem.variableLength)
        
        if let button = statusItem?.button {
            let icon = NSImage(named: "ventry-logo-white")
            icon?.isTemplate = true
            icon?.size = NSSize(width: 18, height: 18)
            button.image = icon
            
            let menu = NSMenu()
            menu.addItem(NSMenuItem(title: "Show Window", action: #selector(showWindow), keyEquivalent: ""))
            menu.addItem(NSMenuItem.separator())
            menu.addItem(NSMenuItem(title: "Quit", action: #selector(NSApplication.terminate(_:)), keyEquivalent: "q"))
            
            statusItem?.menu = menu
        }
    }
    
    @objc private func showWindow() {
        WindowManager.shared.showWindow()
    }
}
