import Foundation
import SwiftUI
import UIKit
import TetherKit

/// Observable bridge between `TetherClient` (transport) and SwiftUI.
/// Owns the receive task and the local clipboard side-effects.
@MainActor @Observable
final class TetherStore {
    var serverURL: String = UserDefaults.standard.string(forKey: "serverURL") ?? "http://tether.lan:8765"
    var room: String = RoomIdentity.derive()
    var feed: [Message] = []
    var connected = false
    var lastError: String?

    private let deviceID = UIDevice.current.identifierForVendor?.uuidString ?? UUID().uuidString
    private var client: TetherClient?
    private var receiveTask: Task<Void, Never>?

    func connectIfSaved() {
        guard UserDefaults.standard.string(forKey: "serverURL") != nil else { return }
        connect()
    }

    func connect() {
        guard let base = URL(string: serverURL.trimmingCharacters(in: .whitespaces)),
              !room.isEmpty else {
            lastError = "Set a server URL first."
            return
        }
        UserDefaults.standard.set(serverURL, forKey: "serverURL")
        disconnect()

        let cfg = TetherClient.Config(baseURL: base, room: room, from: deviceID)
        let c = TetherClient(config: cfg)
        client = c
        connected = true
        lastError = nil
        receiveTask = Task {
            for await msg in await c.clipboardStream() {
                feed.insert(msg, at: 0)
                if feed.count > 100 { feed.removeLast() }
            }
            connected = false
        }
    }

    func disconnect() {
        receiveTask?.cancel()
        receiveTask = nil
        connected = false
    }

    /// Read the system pasteboard (foreground only — iOS bans background reads)
    /// and push it to the room.
    func sendClipboard() {
        guard let text = UIPasteboard.general.string, !text.isEmpty else {
            lastError = "Clipboard is empty."
            return
        }
        send(text)
    }

    func send(_ text: String) {
        guard let c = client else { return }
        Task {
            do { try await c.send(text) }
            catch { lastError = "Send failed: \(error.localizedDescription)" }
        }
    }

    /// Copy a received message back onto the local pasteboard.
    func copyToPasteboard(_ msg: Message) {
        UIPasteboard.general.string = msg.text
    }
}
