//
//  GitSyncConflictSheet.swift
//  Confab
//
//  Recovery UI for Git Sync's "untracked working tree files" pull failure
//
// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0
// Copyright (C) 2026 Rune Olsen
//
// This file is part of Confab.
//
// Confab is licensed under the PolyForm Noncommercial License 1.0.0.
// You may use, study, modify, and share it for any noncommercial
// purpose. Commercial use — including selling Confab or any part of
// it, standalone or bundled into another product or service —
// requires a separate commercial license from the copyright holder.
//
// See the LICENSE file or
// <https://polyformproject.org/licenses/noncommercial/1.0.0> for
// the full license text. For commercial licensing, contact Rune
// Olsen via <https://confab.no>.


import SwiftUI

struct GitSyncConflictSheet: View {
    let pending: GitSyncService.PendingGitConflict
    /// Performs the automatic fix; nil return means success.
    let onFixForMe: () async -> String?
    /// Swaps this sheet for GitSyncManualFixSheet's in-app step-by-step instructions.
    let onFixMyself: () -> Void
    let onDismiss: () -> Void

    private enum RecoveryState: Equatable {
        case idle
        case fixing
        case succeeded
        case failed(String)
    }

    @State private var recoveryState: RecoveryState = .idle

    var body: some View {
        VStack(alignment: .leading, spacing: 20) {
            // Header
            HStack(spacing: 12) {
                Image(systemName: "exclamationmark.arrow.triangle.2.circlepath")
                    .font(.title2)
                    .foregroundStyle(.orange)
                VStack(alignment: .leading, spacing: 2) {
                    Text("Sync Ran Into a Conflict")
                        .font(.system(size: 17, weight: .semibold))
                    Text("Confab syncs in the background automatically, and just hit a file that collided with a leftover local copy of itself")
                        .font(.system(size: 13))
                        .foregroundStyle(.secondary)
                        .fixedSize(horizontal: false, vertical: true)
                }
                Spacer()
            }

            // Conflicting files
            VStack(alignment: .leading, spacing: 6) {
                Text("AFFECTED FILES")
                    .font(.system(size: 11, weight: .medium))
                    .foregroundStyle(.secondary)
                VStack(alignment: .leading, spacing: 4) {
                    ForEach(pending.files, id: \.self) { file in
                        Text(file)
                            .font(.system(size: 13, design: .monospaced))
                    }
                }
                .frame(maxWidth: .infinity, alignment: .leading)
                .textSelection(.enabled)
                .padding(12)
                .background(Color.secondary.opacity(0.08))
                .clipShape(RoundedRectangle(cornerRadius: 8))
                .overlay(
                    RoundedRectangle(cornerRadius: 8)
                        .stroke(Color.secondary.opacity(0.2), lineWidth: 1)
                )
            }

            Text("These are Confab's own sync bookkeeping files, not your conversations — nothing you've written is at risk either way.")
                .font(.system(size: 12))
                .foregroundStyle(.secondary)
                .fixedSize(horizontal: false, vertical: true)

            statusBanner

            if !pending.canAutoFix {
                HStack(alignment: .top, spacing: 8) {
                    Image(systemName: "exclamationmark.triangle.fill")
                        .foregroundStyle(.orange)
                        .font(.system(size: 13))
                        .padding(.top, 1)
                    Text("One or more of these files aren't ones Confab recognizes as safe to remove automatically — please fix this one yourself.")
                        .font(.system(size: 12))
                        .foregroundStyle(.secondary)
                        .fixedSize(horizontal: false, vertical: true)
                }
                .padding(10)
                .background(Color.orange.opacity(0.08))
                .clipShape(RoundedRectangle(cornerRadius: 8))
            }

            // Buttons
            HStack(spacing: 8) {
                Button("Fix It Myself") {
                    onFixMyself()
                }
                .buttonStyle(.bordered)
                .keyboardShortcut(.escape, modifiers: [])

                Spacer()

                if recoveryState == .succeeded {
                    Button("Done") {
                        onDismiss()
                    }
                    .buttonStyle(.borderedProminent)
                    .keyboardShortcut(.return, modifiers: [])
                } else {
                    Button("Fix It For Me") {
                        recoveryState = .fixing
                        Task {
                            if let errorMessage = await onFixForMe() {
                                recoveryState = .failed(errorMessage)
                            } else {
                                recoveryState = .succeeded
                            }
                        }
                    }
                    .buttonStyle(.borderedProminent)
                    .disabled(!pending.canAutoFix || recoveryState == .fixing)
                    .keyboardShortcut(.return, modifiers: [])
                }
            }
        }
        .padding(24)
        .frame(width: 480)
    }

    @ViewBuilder
    private var statusBanner: some View {
        switch recoveryState {
        case .idle:
            EmptyView()
        case .fixing:
            HStack(spacing: 8) {
                ProgressView().controlSize(.small)
                Text("Fixing...")
                    .font(.system(size: 13))
                    .foregroundStyle(.secondary)
            }
        case .succeeded:
            HStack(spacing: 8) {
                Image(systemName: "checkmark.circle.fill")
                    .foregroundStyle(.green)
                Text("Fixed — your conversations are back in sync.")
                    .font(.system(size: 13))
                    .foregroundStyle(.secondary)
            }
        case .failed(let message):
            HStack(alignment: .top, spacing: 8) {
                Image(systemName: "xmark.circle.fill")
                    .foregroundStyle(.red)
                    .font(.system(size: 13))
                    .padding(.top, 1)
                Text("Still couldn't sync: \(message)")
                    .font(.system(size: 12))
                    .foregroundStyle(.secondary)
                    .fixedSize(horizontal: false, vertical: true)
            }
        }
    }
}
