import Observation
import SwiftUI
import UIKit

struct SybilSidebarView: View {
    @Bindable var viewModel: SybilViewModel

    private func isSelected(_ item: SidebarItem) -> Bool {
        viewModel.draftKind == nil && viewModel.selectedItem == item.selection
    }

    var body: some View {
        VStack(spacing: 0) {
            VStack(alignment: .leading, spacing: 14) {
                VStack(spacing: 10) {
                    sidebarActionButton(
                        title: "New chat",
                        systemImage: "plus",
                        isPrimary: true,
                        isActive: viewModel.draftKind == .chat
                    ) {
                        viewModel.startNewChat()
                    }

                    sidebarActionButton(
                        title: "New search",
                        systemImage: "magnifyingglass",
                        isPrimary: false,
                        isActive: viewModel.draftKind == .search
                    ) {
                        viewModel.startNewSearch()
                    }
                }
            }
            .padding(.horizontal, 12)
            .padding(.top, 18)
            .padding(.bottom, 10)

            Divider()
                .overlay(SybilTheme.border)

            if let errorMessage = viewModel.errorMessage {
                Text(errorMessage)
                    .font(.sybil(.footnote))
                    .foregroundStyle(SybilTheme.danger)
                    .frame(maxWidth: .infinity, alignment: .leading)
                    .padding(.horizontal, 12)
                    .padding(.vertical, 10)

                Divider()
                    .overlay(SybilTheme.border)
            }

            SybilSidebarItemList(
                viewModel: viewModel,
                isSelected: isSelected,
                onSelect: { item in
                    viewModel.select(item.selection)
                }
            )

        }
        .background(SybilTheme.panelGradient)
        .navigationTitle("")
        .navigationBarTitleDisplayMode(.inline)
        .toolbar {
            ToolbarItem(placement: .topBarLeading) {
                SybilWordmark(size: 18)
            }

            ToolbarItem(placement: .topBarTrailing) {
                Button {
                    viewModel.openSettings()
                } label: {
                    Image(systemName: viewModel.selectedItem == .settings ? "gearshape.fill" : "gearshape")
                        .font(.system(size: 16, weight: .semibold))
                        .foregroundStyle(viewModel.selectedItem == .settings ? SybilTheme.primary : SybilTheme.textMuted)
                }
                .accessibilityLabel("Settings")
            }
        }
    }

    private func sidebarActionButton(
        title: String,
        systemImage: String,
        isPrimary: Bool,
        isActive: Bool,
        action: @escaping () -> Void
    ) -> some View {
        Button(action: action) {
            Label(title, systemImage: systemImage)
                .font(.sybil(.subheadline, weight: .semibold))
                .foregroundStyle(isPrimary ? SybilTheme.text : SybilTheme.text.opacity(0.92))
                .padding(.horizontal, 13)
                .padding(.vertical, 11)
                .frame(maxWidth: .infinity, alignment: .leading)
                .background(
                    RoundedRectangle(cornerRadius: 11)
                        .fill(isPrimary ? SybilTheme.primaryGradient : LinearGradient(colors: [SybilTheme.surface.opacity(0.86), SybilTheme.surface.opacity(0.62)], startPoint: .topLeading, endPoint: .bottomTrailing))
                )
                .overlay(
                    RoundedRectangle(cornerRadius: 11)
                        .stroke(isActive ? SybilTheme.primary.opacity(0.70) : SybilTheme.border.opacity(isPrimary ? 0.28 : 0.72), lineWidth: 1)
                )
        }
        .buttonStyle(.plain)
    }
}

struct SybilSidebarItemList: View {
    @Bindable var viewModel: SybilViewModel
    var isSelected: (SidebarItem) -> Bool
    var onSelect: (SidebarItem) -> Void
    var onOpenForkedChat: ((String) -> Void)? = nil
    @State private var renameTarget: SidebarItem?
    @State private var renameTitle = ""

    private var isRenameAlertPresented: Binding<Bool> {
        Binding {
            renameTarget != nil
        } set: { isPresented in
            if !isPresented {
                renameTarget = nil
                renameTitle = ""
            }
        }
    }

    var body: some View {
        Group {
            if viewModel.isLoadingCollections && viewModel.sidebarItems.isEmpty {
                VStack(alignment: .leading, spacing: 8) {
                    ProgressView()
                        .tint(SybilTheme.primary)
                    Text("Loading conversations…")
                        .font(.sybil(.footnote))
                        .foregroundStyle(SybilTheme.textMuted)
                }
                .frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .topLeading)
                .padding(16)
            } else if viewModel.sidebarItems.isEmpty {
                VStack(spacing: 10) {
                    Image(systemName: "message.badge")
                        .font(.system(size: 20, weight: .medium))
                        .foregroundStyle(SybilTheme.textMuted)
                    Text("Start a chat or run your first search.")
                        .font(.sybil(.footnote))
                        .multilineTextAlignment(.center)
                        .foregroundStyle(SybilTheme.textMuted)
                }
                .frame(maxWidth: .infinity, maxHeight: .infinity)
                .padding(16)
            } else {
                ScrollView {
                    LazyVStack(alignment: .leading, spacing: 8) {
                        ForEach(viewModel.sidebarItems) { item in
                            Button {
                                onSelect(item)
                            } label: {
                                SybilSidebarRow(item: item, isSelected: isSelected(item))
                            }
                            .buttonStyle(.plain)
                            .contextMenu {
                                Button {
                                    Task {
                                        await viewModel.setItemStarred(item.selection, starred: !item.starred)
                                    }
                                } label: {
                                    Label(item.starred ? "Unstar" : "Star", systemImage: item.starred ? "star.slash" : "star")
                                }

                                if case let .chat(chatID) = item.selection {
                                    Button {
                                        forkChat(item)
                                    } label: {
                                        Label("Fork", systemImage: "arrow.triangle.branch")
                                    }
                                    .disabled(viewModel.isForkingChat || item.isRunning)

                                    Button {
                                        renameTarget = item
                                        renameTitle = item.title
                                    } label: {
                                        Label("Rename", systemImage: "pencil")
                                    }

                                    Button {
                                        UIPasteboard.general.string = chatID
                                    } label: {
                                        Label("Copy Session ID", systemImage: "doc.on.doc")
                                    }
                                }

                                Button(role: .destructive) {
                                    Task {
                                        await viewModel.deleteItem(item.selection)
                                    }
                                } label: {
                                    Label("Delete", systemImage: "trash")
                                }
                            }
                        }
                    }
                    .padding(10)
                }
                .refreshable {
                    await viewModel.refreshSidebarCollectionsFromPullToRefresh()
                }
            }
        }
        .alert("Rename Chat", isPresented: isRenameAlertPresented) {
            TextField("Title", text: $renameTitle)
            Button("Cancel", role: .cancel) {
                renameTarget = nil
                renameTitle = ""
            }
            Button("Save") {
                let target = renameTarget
                let title = renameTitle
                renameTarget = nil
                renameTitle = ""

                if let target, case let .chat(chatID) = target.selection {
                    Task {
                        await viewModel.renameChat(chatID: chatID, title: title)
                    }
                }
            }
            .disabled(renameTitle.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty)
        }
    }

    private func forkChat(_ item: SidebarItem) {
        guard case let .chat(chatID) = item.selection else {
            return
        }

        let selectionAtStart = viewModel.selectedItem
        let draftKindAtStart = viewModel.draftKind
        Task {
            guard let forkedChat = await viewModel.forkChat(chatID: chatID),
                  viewModel.selectedItem == selectionAtStart,
                  viewModel.draftKind == draftKindAtStart else {
                return
            }

            if let onOpenForkedChat {
                onOpenForkedChat(forkedChat.id)
            } else {
                viewModel.select(.chat(forkedChat.id))
            }
        }
    }
}

struct SybilSidebarRow: View {
    var item: SidebarItem
    var isSelected: Bool

    private var isHighlighted: Bool {
        isSelected
    }

    private var iconName: String {
        switch item.kind {
        case .chat: return "message"
        case .search: return "globe"
        }
    }

    var body: some View {
        VStack(alignment: .leading, spacing: 6) {
            HStack(spacing: 8) {
                Image(systemName: iconName)
                    .font(.system(size: 12, weight: .semibold))
                    .foregroundStyle(isHighlighted ? SybilTheme.accent : SybilTheme.textMuted)
                    .frame(width: 22, height: 22)
                    .background(
                        RoundedRectangle(cornerRadius: 7)
                            .fill(isHighlighted ? SybilTheme.accent.opacity(0.12) : SybilTheme.surface.opacity(0.72))
                            .overlay(
                                RoundedRectangle(cornerRadius: 7)
                                    .stroke(isHighlighted ? SybilTheme.accent.opacity(0.36) : SybilTheme.border.opacity(0.72), lineWidth: 1)
                            )
                    )

                Text(item.title)
                    .font(.sybil(.subheadline, weight: .semibold))
                    .lineLimit(1)
                    .layoutPriority(1)

                if item.starred {
                    Image(systemName: "star.fill")
                        .font(.system(size: 10, weight: .semibold))
                        .foregroundStyle(.yellow)
                }

                Spacer(minLength: 8)

                if item.isRunning {
                    SybilSidebarActivityIndicator()
                }
            }

            HStack(spacing: 8) {
                Text(item.updatedAt.sybilRelativeLabel)
                    .font(.sybil(.caption2))
                    .foregroundStyle(SybilTheme.textMuted)

                if let initiated = item.initiatedLabel {
                    Spacer(minLength: 0)
                    Text(initiated)
                        .font(.sybil(.caption2))
                        .foregroundStyle(SybilTheme.textMuted.opacity(0.88))
                        .lineLimit(1)
                        .multilineTextAlignment(.trailing)
                        .frame(maxWidth: .infinity, alignment: .trailing)
                }
            }
        }
        .foregroundStyle(SybilTheme.text)
        .padding(.horizontal, 12)
        .padding(.vertical, 10)
        .frame(maxWidth: .infinity, alignment: .leading)
        .background(
            RoundedRectangle(cornerRadius: 12)
                .fill(isHighlighted ? SybilTheme.selectedRowGradient : LinearGradient(colors: [SybilTheme.surface.opacity(0.56), SybilTheme.surface.opacity(0.36)], startPoint: .topLeading, endPoint: .bottomTrailing))
        )
        .overlay(
            RoundedRectangle(cornerRadius: 12)
                .stroke(isHighlighted ? SybilTheme.primary.opacity(0.55) : SybilTheme.border.opacity(0.72), lineWidth: 1)
        )
        .contentShape(RoundedRectangle(cornerRadius: 12))
    }
}

struct SybilSidebarActivityIndicator: View {
    var body: some View {
        ProgressView()
            .progressViewStyle(.circular)
            .controlSize(.small)
            .tint(SybilTheme.accent)
            .scaleEffect(0.82)
            .frame(width: 16, height: 16)
            .accessibilityLabel("Generating")
    }
}
