import SwiftUI
import MijickCamera
import Bedrock



struct ContentView: View {
    @State private var settings = SettingsViewModel()
    @State private var premiumManager = PremiumManager()
    @State private var showSettings = false
    @State private var showPaywall = false

    @State private var capturedPhoto: CapturedPhoto?
    @State private var showPhotoReview = false
    @State private var isSavingPhoto = false
    @State private var saveError: String?

    /// Settings are managed by SettingsViewModel which is already @Observable

    /// Unique key to force MCamera recreation after photo capture
    /// Incrementing this value creates a new camera session with fresh AVCapturePhotoOutput
    @State private var cameraSessionKey = UUID()

    var body: some View {
        ZStack {
            // Camera view - wrapped in EquatableView to prevent re-evaluation on settings changes
            if !showPhotoReview {
                EquatableView(content: CameraContainerView(
                    settings: settings,
                    sessionKey: cameraSessionKey,
                    onImageCaptured: { image in
                        handlePhotoCaptured(image)
                    }
                ))
                .ignoresSafeArea() // Only camera ignores safe area to fill screen
            }

            // Photo review overlay
            if showPhotoReview, let photo = capturedPhoto {
                PhotoReviewView(
                    photo: photo,
                    isSaving: isSavingPhoto,
                    saveError: saveError,
                    onRetake: {
                        resetCameraForNextCapture()
                    },
                    onSave: {
                        savePhotoToLibrary(photo.image)
                    }
                )
                .transition(.opacity)
                .ignoresSafeArea() // Photo review also fills screen
            }
        }
        // Settings button overlay - respects safe area naturally
        .overlay(alignment: .topTrailing) {
            Button {
                showSettings = true
            } label: {
                Image(systemName: "gearshape.fill")
                    .font(.title3)
                    .foregroundStyle(.white)
                    .padding(Design.Spacing.medium)
                    .background(.ultraThinMaterial, in: Circle())
                    .shadow(radius: Design.Shadow.radiusSmall)
            }
            .accessibilityLabel("Settings")
            .padding(.horizontal, Design.Spacing.large)
            .padding(.top, Design.Spacing.small)
        }
        .animation(.easeInOut(duration: Design.Animation.quick), value: showPhotoReview)
        .onChange(of: settings.isRingLightEnabled) { _, newValue in
            if settings.isFlashSyncedWithRingLight {
                settings.flashMode = newValue ? .on : .off
            }
        }
        .onChange(of: settings.isFlashSyncedWithRingLight) { _, newValue in
            if newValue {
                settings.flashMode = settings.isRingLightEnabled ? .on : .off
            }
        }
        .sheet(isPresented: $showSettings) {
            SettingsView(viewModel: settings, showPaywall: $showPaywall)
        }
        .sheet(isPresented: $showPaywall) {
            ProPaywallView()
        }
    }

    /// Handles photo capture - either auto-saves or shows review screen
    private func handlePhotoCaptured(_ image: UIImage) {
        if settings.isAutoSaveEnabled {
            // Auto-save enabled: save immediately without showing review screen
            Task {
                // Small delay to ensure shutter sound plays before saving
                try? await Task.sleep(for: .milliseconds(200))

                let quality = settings.photoQuality
                let result = await PhotoLibraryService.savePhotoToLibrary(image, quality: quality)

                switch result {
                case .success:
                    Design.debugLog("Photo auto-saved successfully")
                    // Don't reset camera session for auto-save to avoid timing issues
                case .failure(let error):
                    Design.debugLog("Failed to auto-save photo: \(error)")
                    // Don't reset on failure either
                }
            }
        } else {
            // Auto-save disabled: show review screen
            capturedPhoto = CapturedPhoto(image: image, timestamp: Date())
            showPhotoReview = true
            isSavingPhoto = false
            saveError = nil
        }
    }

    /// Resets state and regenerates camera session key to create a fresh camera instance
    private func resetCameraForNextCapture() {
        capturedPhoto = nil
        showPhotoReview = false
        isSavingPhoto = false
        saveError = nil
        // Generate new key to force MCamera recreation with fresh AVCapturePhotoOutput
        cameraSessionKey = UUID()
    }

    private func savePhotoToLibrary(_ image: UIImage) {
        isSavingPhoto = true
        saveError = nil

        let quality = settings.photoQuality

        Task {
            let result = await PhotoLibraryService.savePhotoToLibrary(image, quality: quality)

            await MainActor.run {
                self.isSavingPhoto = false

                switch result {
                case .success:
                    Design.debugLog("Photo saved successfully")
                    // Auto-dismiss after successful save and reset camera for next capture
                    Task {
                        try? await Task.sleep(for: .seconds(1.5))
                        await MainActor.run {
                            self.resetCameraForNextCapture()
                        }
                    }
                case .failure(let error):
                    Design.debugLog("Failed to save photo: \(error)")
                    self.saveError = error.localizedDescription
                }
            }
        }
    }
}

// MARK: - Camera Container View
/// Wrapper view for MCamera - only recreates when sessionKey changes
struct CameraContainerView: View, Equatable {
    let settings: SettingsViewModel
    let sessionKey: UUID
    let onImageCaptured: (UIImage) -> Void

    // Only compare sessionKey for equality - ignore settings and callback changes
    static func == (lhs: CameraContainerView, rhs: CameraContainerView) -> Bool {
        lhs.sessionKey == rhs.sessionKey
    }

    var body: some View {
        let _ = Design.debugLog("CameraContainerView body evaluated - sessionKey: \(sessionKey)")
        MCamera()
            .setCameraScreen { cameraManager, namespace, closeAction in
                CustomCameraScreen(
                    cameraManager: cameraManager,
                    namespace: namespace,
                    closeMCameraAction: closeAction,
                    cameraSettings: settings,
                    onPhotoCaptured: onImageCaptured
                )
            }
            .setCapturedMediaScreen(nil)
            // Use front camera as default for selfie app - don't read from settings here
            // to avoid triggering @Observable tracking which breaks the camera
            .setCameraPosition(.front)
            .startSession()
    }
}

#Preview {
    ContentView()
}
