import SwiftUI
import Bedrock
import AVFoundation
import Photos
import Contacts

struct OnboardingView: View {
    @Environment(AppState.self) private var appState
    let onComplete: () -> Void

    @State private var step: OnboardingStep = .welcome
    @State private var cameraStatus: OnboardingPermissionStatus = .notRequested
    @State private var photosStatus: OnboardingPermissionStatus = .notRequested
    @State private var contactsStatus: OnboardingPermissionStatus = .notRequested

    private let appName = AppIdentifiers.publicAppName

    var body: some View {
        NavigationStack {
            ZStack {
                Color.AppBackground.base
                    .ignoresSafeArea()

                VStack(spacing: Design.Spacing.large) {
                    OnboardingProgressHeaderView(step: step)

                    currentStepContent

                    Spacer(minLength: 0)

                    primaryAction
                }
                .padding(.horizontal, Design.Spacing.large)
                .padding(.top, Design.Spacing.large)
                .padding(.bottom, Design.Spacing.xLarge)
            }
            .toolbar {
                ToolbarItem(placement: .topBarTrailing) {
                    if step != .activation {
                        Button(String.localized("Skip")) {
                            onComplete()
                        }
                    }
                }
            }
            .onAppear {
                refreshPermissionStatuses()
            }
        }
        .preferredColorScheme(appState.preferredColorScheme)
    }

    @ViewBuilder
    private var currentStepContent: some View {
        switch step {
        case .welcome:
            ScrollView(.vertical) {
                OnboardingWelcomeStepView(appName: appName)
                    .padding(.top, Design.Spacing.xSmall)
            }
            .scrollIndicators(.hidden)
        case .camera:
            OnboardingPermissionStepView(
                title: "Camera Access",
                icon: "camera.fill",
                reason: "Needed to scan QR cards and capture profile, cover, or logo photos.",
                status: cameraStatus
            )
        case .photos:
            OnboardingPermissionStepView(
                title: "Photo Library",
                icon: "photo.on.rectangle.angled",
                reason: "Needed to pick profile, cover, and logo images from your library.",
                status: photosStatus
            )
        case .contacts:
            OnboardingPermissionStepView(
                title: "Contacts Access",
                icon: "person.crop.circle.badge.plus",
                reason: "Needed when saving shared cards to your Apple Contacts.",
                status: contactsStatus
            )
        case .activation:
            OnboardingActivationStepView()
        }
    }

    @ViewBuilder
    private var primaryAction: some View {
        switch step {
        case .camera:
            permissionPrimaryButton(status: cameraStatus, permissionName: "Camera", requestAction: requestCameraPermission)
        case .photos:
            permissionPrimaryButton(status: photosStatus, permissionName: "Photos", requestAction: requestPhotosPermission)
        case .contacts:
            permissionPrimaryButton(status: contactsStatus, permissionName: "Contacts", requestAction: requestContactsPermission)
        case .activation:
            PrimaryActionButton(
                title: String.localized("Create My First Card"),
                systemImage: "sparkles"
            ) {
                appState.selectedTab = .cards
                appState.shouldPresentCreateCardFlow = true
                onComplete()
            }
        case .welcome:
            PrimaryActionButton(
                title: String.localized("Continue"),
                systemImage: "arrow.right"
            ) {
                advanceStep()
            }
        }
    }

    private func permissionPrimaryButton(
        status: OnboardingPermissionStatus,
        permissionName: String,
        requestAction: @escaping () -> Void
    ) -> some View {
        let title: String
        let systemImage: String
        let action: () -> Void

        switch status {
        case .allowed:
            title = "Continue"
            systemImage = "arrow.right"
            action = advanceStep
        case .denied:
            title = "Open Settings"
            systemImage = "gear"
            action = openSettings
        case .notRequested:
            title = "Enable \(permissionName)"
            systemImage = "checkmark.shield"
            action = requestAction
        }

        return PrimaryActionButton(title: title, systemImage: systemImage, action: action)
    }

    private func advanceStep() {
        guard let next = step.next else { return }
        withAnimation(.easeInOut(duration: 0.2)) {
            step = next
        }
    }

    private func openSettings() {
        guard let url = URL(string: UIApplication.openSettingsURLString) else { return }
        UIApplication.shared.open(url)
    }

    private func refreshPermissionStatuses() {
        cameraStatus = mapCameraStatus(AVCaptureDevice.authorizationStatus(for: .video))
        photosStatus = mapPhotosStatus(PHPhotoLibrary.authorizationStatus(for: .readWrite))
        contactsStatus = mapContactsStatus(CNContactStore.authorizationStatus(for: .contacts))
    }

    private func requestCameraPermission() {
        AVCaptureDevice.requestAccess(for: .video) { granted in
            Task { @MainActor in
                refreshPermissionStatuses()
                if granted, step == .camera {
                    advanceStep()
                }
            }
        }
    }

    private func requestPhotosPermission() {
        PHPhotoLibrary.requestAuthorization(for: .readWrite) { status in
            Task { @MainActor in
                refreshPermissionStatuses()
                if (status == .authorized || status == .limited), step == .photos {
                    advanceStep()
                }
            }
        }
    }

    private func requestContactsPermission() {
        CNContactStore().requestAccess(for: .contacts) { granted, _ in
            Task { @MainActor in
                refreshPermissionStatuses()
                if granted, step == .contacts {
                    advanceStep()
                }
            }
        }
    }

    private func mapCameraStatus(_ status: AVAuthorizationStatus) -> OnboardingPermissionStatus {
        switch status {
        case .authorized:
            .allowed
        case .notDetermined:
            .notRequested
        case .denied, .restricted:
            .denied
        @unknown default:
            .notRequested
        }
    }

    private func mapPhotosStatus(_ status: PHAuthorizationStatus) -> OnboardingPermissionStatus {
        switch status {
        case .authorized, .limited:
            .allowed
        case .notDetermined:
            .notRequested
        case .denied, .restricted:
            .denied
        @unknown default:
            .notRequested
        }
    }

    private func mapContactsStatus(_ status: CNAuthorizationStatus) -> OnboardingPermissionStatus {
        switch status {
        case .authorized:
            .allowed
        case .notDetermined:
            .notRequested
        case .denied, .restricted:
            .denied
        @unknown default:
            .notRequested
        }
    }
}

#Preview {
    OnboardingView(onComplete: {})
}
