import SwiftUI
import UIKit

struct DeveloperLogEntry: Identifiable, Equatable {
    enum Level: String {
        case info = "信息"
        case success = "成功"
        case warning = "警告"
        case error = "错误"
        case transmit = "发送"
        case receive = "接收"
    }

    let id = UUID()
    let timestamp: Date
    let category: String
    let level: Level
    let message: String
}

final class DeveloperLogStore: ObservableObject, @unchecked Sendable {
    static let shared = DeveloperLogStore()
    static let enabledKey = "com.celestia.trace.developer_mode"

    @Published private(set) var entries: [DeveloperLogEntry] = []

    private init() {}

    static func log(
        _ category: String,
        _ message: String,
        level: DeveloperLogEntry.Level = .info
    ) {
        guard UserDefaults.standard.bool(forKey: enabledKey) else { return }
        let entry = DeveloperLogEntry(
            timestamp: Date(),
            category: category,
            level: level,
            message: message
        )
        DispatchQueue.main.async {
            shared.entries.append(entry)
            if shared.entries.count > 500 {
                shared.entries.removeFirst(shared.entries.count - 500)
            }
        }
    }

    func clear() {
        entries.removeAll()
    }

    var copyableText: String {
        entries.map { entry in
            "\(Self.timestampFormatter.string(from: entry.timestamp)) [\(entry.category)] [\(entry.level.rawValue)] \(entry.message)"
        }
        .joined(separator: "\n")
    }

    private static let timestampFormatter: DateFormatter = {
        let formatter = DateFormatter()
        formatter.locale = Locale(identifier: "zh_CN")
        formatter.dateFormat = "HH:mm:ss.SSS"
        return formatter
    }()
}

struct DeveloperLogOverlay: View {
    @ObservedObject private var logStore = DeveloperLogStore.shared
    @State private var isCollapsed = false
    @State private var dragOffset: CGSize = .zero
    @State private var dragStartOffset: CGSize = .zero

    var body: some View {
        VStack(spacing: 0) {
            header

            if !isCollapsed {
                Divider()
                    .overlay(Color.white.opacity(0.12))

                ScrollViewReader { proxy in
                    ScrollView {
                        LazyVStack(alignment: .leading, spacing: 7) {
                            if logStore.entries.isEmpty {
                                Text("等待蓝牙、同步及 App 运行日志…")
                                    .foregroundStyle(.white.opacity(0.55))
                            } else {
                                ForEach(logStore.entries) { entry in
                                    logRow(entry)
                                        .id(entry.id)
                                }
                            }
                        }
                        .frame(maxWidth: .infinity, alignment: .leading)
                        .padding(10)
                    }
                    .frame(height: 210)
                    .onChange(of: logStore.entries.last?.id) { _, id in
                        guard let id else { return }
                        withAnimation(.easeOut(duration: 0.15)) {
                            proxy.scrollTo(id, anchor: .bottom)
                        }
                    }
                }
            }
        }
        .containerRelativeFrame(.horizontal) { availableWidth, _ in
            min(max(availableWidth - 24, 240), 340)
        }
        .background(.black.opacity(0.88), in: RoundedRectangle(cornerRadius: 12))
        .overlay {
            RoundedRectangle(cornerRadius: 12)
                .stroke(Color.celestiaCyan.opacity(0.65), lineWidth: 1)
        }
        .shadow(color: .black.opacity(0.35), radius: 12, y: 5)
        .offset(dragOffset)
        .padding(.horizontal, 12)
        .padding(.bottom, 62)
        .accessibilityElement(children: .contain)
        .accessibilityLabel("开发者日志悬浮框")
    }

    private var header: some View {
        HStack(spacing: 10) {
            Circle()
                .fill(Color.green)
                .frame(width: 7, height: 7)
            Text("开发者日志")
                .font(.system(size: 13, weight: .semibold, design: .monospaced))
                .foregroundStyle(.white)

            Spacer()

            Text("\(logStore.entries.count)")
                .font(.system(size: 11, design: .monospaced))
                .foregroundStyle(.white.opacity(0.55))

            Button {
                UIPasteboard.general.string = logStore.copyableText
            } label: {
                Image(systemName: "doc.on.doc")
            }
            .disabled(logStore.entries.isEmpty)

            Button {
                logStore.clear()
            } label: {
                Image(systemName: "trash")
            }
            .disabled(logStore.entries.isEmpty)

            Button {
                withAnimation(.easeInOut(duration: 0.18)) {
                    isCollapsed.toggle()
                }
            } label: {
                Image(systemName: isCollapsed ? "chevron.up" : "chevron.down")
            }
        }
        .font(.system(size: 12, weight: .medium))
        .foregroundStyle(Color.celestiaCyan)
        .padding(.horizontal, 11)
        .frame(height: 40)
        .contentShape(Rectangle())
        .gesture(
            DragGesture()
                .onChanged { value in
                    dragOffset = CGSize(
                        width: dragStartOffset.width + value.translation.width,
                        height: dragStartOffset.height + value.translation.height
                    )
                }
                .onEnded { _ in
                    dragStartOffset = dragOffset
                }
        )
    }

    private func logRow(_ entry: DeveloperLogEntry) -> some View {
        VStack(alignment: .leading, spacing: 2) {
            HStack(spacing: 5) {
                Text(Self.timeFormatter.string(from: entry.timestamp))
                    .foregroundStyle(.white.opacity(0.46))
                Text(entry.category)
                    .foregroundStyle(Color.celestiaCyan)
                Text(entry.level.rawValue)
                    .foregroundStyle(color(for: entry.level))
            }
            Text(entry.message)
                .foregroundStyle(.white.opacity(0.9))
                .fixedSize(horizontal: false, vertical: true)
        }
        .font(.system(size: 10, design: .monospaced))
        .textSelection(.enabled)
    }

    private func color(for level: DeveloperLogEntry.Level) -> Color {
        switch level {
        case .info: .white.opacity(0.7)
        case .success: .green
        case .warning: .yellow
        case .error: .red
        case .transmit: .orange
        case .receive: .mint
        }
    }

    private static let timeFormatter: DateFormatter = {
        let formatter = DateFormatter()
        formatter.locale = Locale(identifier: "zh_CN")
        formatter.dateFormat = "HH:mm:ss"
        return formatter
    }()
}
