//
// DuplicateCleanupView.swift
// Workouts
//
// Copyright 2025 Rouslan Zenetl. All Rights Reserved.
//

import SwiftUI

/// Developer-facing tool: scans iCloud Drive for routines/workouts that are exact
/// content duplicates (see `DuplicateCleanupPlanner`) — typically the residue of
/// testing, a restore, or a sync hiccup — and offers to delete the extras. Never
/// touches a routine referenced by a workout, a bundled starter routine, or an
/// in-progress workout.
struct DuplicateCleanupView: View {
    @Environment(SyncEngine.self) private var sync

    private enum ScanFailure {
        case unreadableFiles([String])
        case other(String)
    }

    private struct CleanupSummary {
        var routinesDeleted: Int
        var workoutsDeleted: Int
        var skipped: Int
    }

    private enum Phase {
        case idle
        case scanning
        case results(DuplicateCleanupPlan)
        case failed(ScanFailure)
        case deleting
        case done(CleanupSummary)
    }

    @State private var phase: Phase = .idle
    @State private var pendingPlan: DuplicateCleanupPlan?

    var body: some View {
        content
            .navigationTitle("Clean Up Duplicates")
            .confirmationDialog(
                "Delete \(pendingPlan?.deleteCount ?? 0) Duplicate\((pendingPlan?.deleteCount ?? 0) == 1 ? "" : "s")?",
                isPresented: Binding(
                    get: { pendingPlan != nil },
                    set: { if !$0 { pendingPlan = nil } }
                ),
                titleVisibility: .visible,
                presenting: pendingPlan
            ) { plan in
                Button("Delete", role: .destructive) {
                    pendingPlan = nil
                    Task { await performDelete(plan) }
                }
                Button("Cancel", role: .cancel) {
                    pendingPlan = nil
                }
            } message: { _ in
                Text("This permanently deletes the duplicate copies shown below. Referenced routines, starter routines, and in-progress workouts are always kept.")
            }
    }

    @ViewBuilder
    private var content: some View {
        switch phase {
        case .idle:
            idleView
        case .scanning:
            ProgressView("Scanning…")
                .frame(maxWidth: .infinity, maxHeight: .infinity)
        case .results(let plan):
            resultsView(plan)
        case .failed(let failure):
            failureView(failure)
        case .deleting:
            ProgressView("Deleting…")
                .frame(maxWidth: .infinity, maxHeight: .infinity)
        case .done(let summary):
            doneView(summary)
        }
    }

    // MARK: - Idle

    private var idleView: some View {
        Form {
            Section {
                Button {
                    Task { await scan() }
                } label: {
                    Label("Scan for Duplicates", systemImage: "magnifyingglass")
                }
            } footer: {
                Text("Looks for routines and workouts that are exact content duplicates — for example, left over from testing or a sync hiccup — and offers to delete the extra copies. Routines referenced by a workout, starter routines, and in-progress workouts are never deleted.")
            }
        }
    }

    // MARK: - Results

    @ViewBuilder
    private func resultsView(_ plan: DuplicateCleanupPlan) -> some View {
        if plan.isEmpty {
            ContentUnavailableView(
                "No Duplicates Found",
                systemImage: "checkmark.circle",
                description: Text("Everything in iCloud looks unique.")
            )
        } else {
            List {
                if !plan.routineGroups.isEmpty {
                    Section("Duplicate Routines") {
                        ForEach(plan.routineGroups) { group in
                            routineGroupRow(group)
                        }
                    }
                }
                if !plan.workoutGroups.isEmpty {
                    Section("Duplicate Workouts") {
                        ForEach(plan.workoutGroups) { group in
                            workoutGroupRow(group)
                        }
                    }
                }
                Section {
                    Button(role: .destructive) {
                        pendingPlan = plan
                    } label: {
                        HStack {
                            Spacer()
                            Text("Delete \(plan.deleteCount) Duplicate\(plan.deleteCount == 1 ? "" : "s")")
                            Spacer()
                        }
                    }
                }
            }
        }
    }

    private func routineGroupRow(_ group: DuplicateCleanupPlan.RoutineGroup) -> some View {
        VStack(alignment: .leading, spacing: 6) {
            ForEach(group.keep) { doc in
                memberRow(name: doc.name, detail: "\(doc.exercises.count) exercises", id: doc.id, isKeep: true)
            }
            ForEach(group.delete) { doc in
                memberRow(name: doc.name, detail: "\(doc.exercises.count) exercises", id: doc.id, isKeep: false)
            }
        }
        .padding(.vertical, 4)
    }

    private func workoutGroupRow(_ group: DuplicateCleanupPlan.WorkoutGroup) -> some View {
        VStack(alignment: .leading, spacing: 6) {
            memberRow(
                name: group.keep.routineName ?? "(no routine)",
                detail: group.keep.start.formattedDate(),
                id: group.keep.id,
                isKeep: true
            )
            ForEach(group.delete) { doc in
                memberRow(
                    name: doc.routineName ?? "(no routine)",
                    detail: doc.start.formattedDate(),
                    id: doc.id,
                    isKeep: false
                )
            }
        }
        .padding(.vertical, 4)
    }

    private func memberRow(name: String, detail: String, id: String, isKeep: Bool) -> some View {
        HStack {
            VStack(alignment: .leading, spacing: 2) {
                Text(name)
                Text("\(detail) · id …\(id.suffix(6))")
                    .font(.caption)
                    .foregroundStyle(.secondary)
            }
            Spacer()
            if isKeep {
                Label("Keep", systemImage: "checkmark.circle")
                    .foregroundStyle(.secondary)
            } else {
                Label("Delete", systemImage: "trash")
                    .foregroundStyle(.red)
            }
        }
    }

    // MARK: - Failure

    @ViewBuilder
    private func failureView(_ failure: ScanFailure) -> some View {
        switch failure {
        case .unreadableFiles(let paths):
            List {
                Section {
                    Label(
                        "Scan aborted: \(paths.count) file\(paths.count == 1 ? "" : "s") could not be read. Nothing was deleted.",
                        systemImage: "exclamationmark.triangle.fill"
                    )
                    .foregroundStyle(.orange)
                }
                Section("Unreadable Files") {
                    ForEach(paths, id: \.self) { path in
                        Text(path)
                            .font(.system(.footnote, design: .monospaced))
                    }
                }
                Section {
                    Button("Rescan") {
                        Task { await scan() }
                    }
                }
            }
        case .other(let message):
            List {
                Section {
                    Label(message, systemImage: "exclamationmark.triangle.fill")
                        .foregroundStyle(.orange)
                }
                Section {
                    Button("Try Again") {
                        Task { await scan() }
                    }
                }
            }
        }
    }

    // MARK: - Done

    private func doneView(_ summary: CleanupSummary) -> some View {
        List {
            Section {
                Label(
                    "Deleted \(summary.routinesDeleted) routine\(summary.routinesDeleted == 1 ? "" : "s"), \(summary.workoutsDeleted) workout\(summary.workoutsDeleted == 1 ? "" : "s"). \(summary.skipped) skipped (referenced or active).",
                    systemImage: "checkmark.circle.fill"
                )
                .foregroundStyle(.green)
            }
            Section {
                Button("Scan Again") {
                    Task { await scan() }
                }
            }
        }
    }

    // MARK: - Actions

    private func scan() async {
        phase = .scanning
        do {
            let plan = try await sync.scanForDuplicates()
            phase = .results(plan)
        } catch let error as SyncEngine.DuplicateScanError {
            switch error {
            case .notConnected:
                phase = .failed(.other("iCloud isn't connected yet. Try again in a moment."))
            case .unreadableFiles(let paths):
                phase = .failed(.unreadableFiles(paths))
            }
        } catch {
            phase = .failed(.other(error.localizedDescription))
        }
    }

    private func performDelete(_ plan: DuplicateCleanupPlan) async {
        phase = .deleting
        let result = await sync.performCleanup(plan)
        phase = .done(CleanupSummary(
            routinesDeleted: result.routinesDeleted,
            workoutsDeleted: result.workoutsDeleted,
            skipped: result.skipped
        ))
    }
}
