import SwiftUI

/// Maps a stored `Project.color` key (see `Models/Project.swift`'s
/// `colorPalette`) to a display color. This is purely a presentation choice
/// and intentionally lives here rather than in `Models/Project.swift`, which
/// is foundation code shared with other features.
extension Project {
    static func displayColor(for key: String?) -> Color {
        switch key {
        case "blue": return .blue
        case "emerald": return .green
        case "amber": return .orange
        case "rose": return .pink
        case "violet": return .purple
        case "slate": return .gray
        default: return .gray
        }
    }
}

/// `GET /api/projects` isn't Pro-gated, so this list is shown to every user —
/// only creating (and, per the backend, renaming/deleting) requires Pro. A
/// free-plan user can therefore see their existing folders read-only-ish;
/// tapping "+" and trying to create one surfaces the paywall instead of a
/// generic error (see `createProject`).
struct ProjectsListView: View {
    @State private var projects: [Project] = []
    @State private var isLoading = false
    @State private var errorMessage: String?
    @State private var showAddSheet = false
    @State private var showPaywall = false

    var body: some View {
        List {
            if projects.isEmpty && !isLoading {
                Text("Noch keine Ordner vorhanden.")
                    .zenithBodySmStyle()
                    .listRowBackground(Color.zenithSurface)
                    .listRowSeparatorTint(Color.zenithBorder)
            }
            ForEach(projects) { project in
                HStack {
                    Rectangle()
                        .fill(Project.displayColor(for: project.color))
                        .frame(width: 12, height: 12)
                    Text(project.name)
                        .zenithBodyStyle()
                    Spacer()
                    Text("\(project.receiptCount)")
                        .zenithLabelMdStyle(color: .zenithMuted)
                }
                .listRowBackground(Color.zenithSurface)
                .listRowSeparatorTint(Color.zenithBorder)
            }
            .onDelete(perform: deleteProjects)
        }
        .zenithListBackground()
        .navigationTitle("Ordner")
        .toolbar {
            ToolbarItem(placement: .navigationBarTrailing) {
                Button {
                    showAddSheet = true
                } label: {
                    Image(systemName: "plus")
                        .foregroundStyle(Color.zenithBlack)
                }
            }
        }
        .task {
            await loadProjects()
        }
        .refreshable {
            await loadProjects()
        }
        .alert("Fehler", isPresented: errorAlertBinding) {
            Button("OK", role: .cancel) {}
        } message: {
            Text(errorMessage ?? "")
        }
        .sheet(isPresented: $showAddSheet) {
            AddProjectSheet(onCreate: createProject)
        }
        .sheet(isPresented: $showPaywall) {
            PaywallView()
        }
    }

    private var errorAlertBinding: Binding<Bool> {
        Binding(
            get: { errorMessage != nil },
            set: { if !$0 { errorMessage = nil } }
        )
    }

    private func loadProjects() async {
        isLoading = true
        defer { isLoading = false }
        do {
            projects = try await ProjectsAPI.list()
        } catch {
            errorMessage = error.localizedDescription
        }
    }

    /// Returns `true` on success so `AddProjectSheet` knows to dismiss
    /// itself. On a `pro_required` failure this dismisses the add sheet
    /// (`showAddSheet = false`) and presents the paywall instead of a
    /// generic error alert — the whole reason this isn't just a plain
    /// `catch { errorMessage = ... }`.
    private func createProject(name: String, color: String?) async -> Bool {
        do {
            let project = try await ProjectsAPI.create(name: name, color: color)
            projects.append(project)
            return true
        } catch let APIError.server(code, _, _) where code == "pro_required" {
            showAddSheet = false
            showPaywall = true
            return false
        } catch {
            errorMessage = error.localizedDescription
            return false
        }
    }

    private func deleteProjects(at offsets: IndexSet) {
        let toDelete = offsets.map { projects[$0] }
        projects.remove(atOffsets: offsets)
        Task {
            for project in toDelete {
                do {
                    try await ProjectsAPI.delete(id: project.id)
                } catch {
                    // Reload from the server so the list reflects reality
                    // rather than guessing the removed row's original index.
                    await loadProjects()
                    errorMessage = error.localizedDescription
                    break
                }
            }
        }
    }
}

/// Simple add-folder sheet: name + a row of tappable color circles built
/// from `Project.colorPalette`. `onCreate` returns whether the create
/// succeeded — on `false` the sheet stays open only if the parent left
/// `showAddSheet` true (it won't, for `pro_required`, but does for any other
/// error so the user can retry without losing their typed name).
private struct AddProjectSheet: View {
    @Environment(\.dismiss) private var dismiss
    @State private var name = ""
    @State private var selectedColor: String? = Project.colorPalette.first
    @State private var isSaving = false
    let onCreate: (String, String?) async -> Bool

    private var trimmedName: String {
        name.trimmingCharacters(in: .whitespacesAndNewlines)
    }

    var body: some View {
        NavigationStack {
            Form {
                Section {
                    ZenithTextField(
                        label: "Name",
                        text: $name,
                        placeholder: "Ordnername"
                    )
                }
                .listRowBackground(Color.zenithSurface)
                .listRowSeparatorTint(Color.zenithBorder)

                Section {
                    HStack(spacing: 12) {
                        ForEach(Project.colorPalette, id: \.self) { colorKey in
                            Rectangle()
                                .fill(Project.displayColor(for: colorKey))
                                .frame(width: 28, height: 28)
                                .overlay {
                                    if selectedColor == colorKey {
                                        Rectangle().strokeBorder(Color.zenithBlack, lineWidth: 2)
                                    }
                                }
                                .onTapGesture {
                                    selectedColor = colorKey
                                }
                        }
                    }
                    .padding(.vertical, 4)
                } header: {
                    Text("Farbe").zenithLabelCapsStyle()
                }
                .listRowBackground(Color.zenithSurface)
                .listRowSeparatorTint(Color.zenithBorder)
            }
            .zenithListBackground()
            .navigationTitle("Neuer Ordner")
            .toolbar {
                ToolbarItem(placement: .cancellationAction) {
                    Button("Abbrechen") { dismiss() }
                }
                ToolbarItem(placement: .confirmationAction) {
                    Button {
                        Task {
                            isSaving = true
                            let success = await onCreate(trimmedName, selectedColor)
                            isSaving = false
                            if success { dismiss() }
                        }
                    } label: {
                        if isSaving {
                            ProgressView()
                        } else {
                            Text("Erstellen")
                        }
                    }
                    .disabled(trimmedName.isEmpty || isSaving)
                }
            }
        }
    }
}
