import SwiftUI

import SwiftUI

@MainActor
class AppState: ObservableObject {
    // API endpoints
    let memoryAPI = "http://localhost:3202/api/memories"
    let portAPI = "http://localhost:3201/api/ports"
    let portStatsAPI = "http://localhost:3201/api/ports/stats"
    let asrStatusAPI = "http://localhost:4125/api/asr-status"

    // Data
    @Published var projects: [Project] = []
    @Published var portStats: PortStats = PortStats()
    @Published var asrStatus: ASRStatus = ASRStatus()
    @Published var isLoading = false
    @Published var lastRefresh: Date?
    @Published var searchText = ""

    // Services status
    @Published var memoryOnline = false
    @Published var portsOnline = false
    @Published var asrOnline = false

    private var refreshTask: Task<Void, Never>?

    init() {
        startAutoRefresh()
    }
    
    deinit {
        refreshTask?.cancel()
    }
    
    private func startAutoRefresh() {
        refreshTask = Task { @MainActor in
            // Initial refresh
            await refresh()
            
            // Auto-refresh every 30 seconds
            while !Task.isCancelled {
                try? await Task.sleep(nanoseconds: 30_000_000_000)
                if !Task.isCancelled {
                    await refresh()
                }
            }
        }
    }

    func refresh() async {
        isLoading = true
        async let p: Void = fetchProjects()
        async let s: Void = fetchPortStats()
        async let a: Void = fetchASRStatus()
        _ = await (p, s, a)
        isLoading = false
        lastRefresh = Date()
    }

    var filteredProjects: [Project] {
        if searchText.isEmpty { return projects }
        let q = searchText.lowercased()
        return projects.filter {
            $0.name.lowercased().contains(q) ||
            $0.slug.lowercased().contains(q) ||
            ($0.what ?? "").lowercased().contains(q)
        }
    }

    var activeProjects: [Project] {
        projects.filter { $0.status == "active" || $0.status == "进行中" }
    }

    // MARK: - Fetch

    private func fetchProjects() async {
        guard let url = URL(string: memoryAPI) else { return }
        do {
            let (data, _) = try await URLSession.shared.data(from: url)
            let decoded = try JSONDecoder().decode([Project].self, from: data)
            projects = decoded
            memoryOnline = true
        } catch {
            memoryOnline = false
        }
    }

    private func fetchPortStats() async {
        guard let url = URL(string: portStatsAPI) else { return }
        do {
            let (data, _) = try await URLSession.shared.data(from: url)
            let decoded = try JSONDecoder().decode(PortStats.self, from: data)
            portStats = decoded
            portsOnline = true
        } catch {
            portsOnline = false
        }
    }

    private func fetchASRStatus() async {
        guard let url = URL(string: asrStatusAPI) else { return }
        do {
            let (data, _) = try await URLSession.shared.data(from: url)
            let decoded = try JSONDecoder().decode(ASRStatus.self, from: data)
            asrStatus = decoded
            asrOnline = true
        } catch {
            asrOnline = false
        }
    }
}

// MARK: - Models

struct Project: Codable, Identifiable {
    var id: String { slug }
    let slug: String
    let name: String
    let path: String?
    let status: String?
    let category: String?
    let what: String?
    let updatedAt: String?
    let eventCount: Int?

    enum CodingKeys: String, CodingKey {
        case slug, name, path, status, category, what
        case updatedAt = "updated_at"
        case eventCount = "event_count"
    }
}

struct PortStats: Codable {
    var total: Int = 0
    var project: Int = 0
    var adhoc: Int = 0
    var legacy: Int = 0
    var running: Int = 0
    var nextBlock: Int?

    enum CodingKeys: String, CodingKey {
        case total, project, adhoc, legacy, running
        case nextBlock = "next_block"
    }
}

struct ASRStatus: Codable {
    var total: Int = 0
    var done: Int = 0
    var failed: Int = 0
    var chars: Int = 0
    var running: Bool = false
}
