import SwiftUI
import Contacts
import PhotosUI
import SwiftData
import OSLog

private let onboardingLogger = Logger(subsystem: "nahbar", category: "Onboarding")

// MARK: - OnboardingContainerView

/// Root container for the first-launch onboarding flow.
/// Phase 1: Profil, Phase 2: Kontakte, Phase 3: Datenschutz.
struct OnboardingContainerView: View {
    let onComplete: () -> Void

    @StateObject private var coordinator = OnboardingCoordinator()
    @Environment(\.contactStore)  private var contactStore
    @Environment(\.modelContext)  private var modelContext

    /// Current tab page index (0 = profile, 1 = contacts).
    @State private var tabPage: Int = 0
    /// Whether the final privacy screen is visible (shown after contacts).
    @State private var showPrivacyScreen: Bool = false

    var body: some View {
        ZStack {
            // ── Background pages (blurred when privacy screen is active) ──────
            TabView(selection: $tabPage) {
                OnboardingProfileView(coordinator: coordinator)
                    .tag(0)

                OnboardingContactImportView(
                    coordinator: coordinator,
                    onContinue: startPrivacyScreen,
                    onSkip: startPrivacyScreen
                )
                .tag(1)
            }
            .tabViewStyle(.page(indexDisplayMode: .never))
            .blur(radius: showPrivacyScreen ? 20 : 0)
            .disabled(showPrivacyScreen)

            // ── Dark overlay when privacy screen shown ────────────────────────
            if showPrivacyScreen {
                Color.black.opacity(0.45)
                    .ignoresSafeArea()
                    .transition(.opacity)
            }

            // ── Privacy screen (final step) ───────────────────────────────────
            if showPrivacyScreen {
                OnboardingPrivacyView(onFinish: finishOnboarding)
                    .transition(.opacity)
            }
        }
        .animation(.easeInOut(duration: 0.35), value: showPrivacyScreen)
        .onChange(of: coordinator.currentStep) { _, step in
            withAnimation(.spring(response: 0.4, dampingFraction: 0.85)) {
                tabPage = min(step.rawValue, 1)
            }
        }
    }

    private func startPrivacyScreen() {
        withAnimation(.easeInOut(duration: 0.35)) {
            showPrivacyScreen = true
        }
    }

    private func finishOnboarding() {
        // 1. Persist user profile
        UserProfileStore.shared.update(
            name: coordinator.firstName,
            birthday: nil,
            gender: coordinator.gender,
            occupation: "",
            location: "",
            likes: "",
            dislikes: "",
            socialStyle: "",
            displayName: coordinator.displayName,
            aboutMe: coordinator.aboutMe
        )

        // 2. Persist selected contacts (local JSON – no network)
        do {
            try contactStore.save(coordinator.selectedContacts)
        } catch {
            onboardingLogger.error("ContactStore.save fehlgeschlagen: \(error.localizedDescription)")
        }

        // 3. Import each selected contact as a Person in SwiftData
        for contact in coordinator.selectedContacts {
            let person = Person(name: contact.fullName)
            if !contact.location.isEmpty { person.location = contact.location }
            modelContext.insert(person)
        }
        if !coordinator.selectedContacts.isEmpty {
            do {
                try modelContext.save()
                onboardingLogger.info("Onboarding: \(coordinator.selectedContacts.count) Kontakt(e) als Person importiert")
            } catch {
                onboardingLogger.error("modelContext.save fehlgeschlagen: \(error.localizedDescription)")
            }
        }

        coordinator.completeOnboarding()
        onComplete()
    }
}

// MARK: - Phase 1: OnboardingProfileView

private struct OnboardingProfileView: View {
    @ObservedObject var coordinator: OnboardingCoordinator

    @State private var selectedItem: PhotosPickerItem? = nil
    @State private var profileImage: UIImage? = nil
    @State private var showingContactPicker = false

    var body: some View {
        ScrollView {
            VStack(spacing: 24) {

                // ── Header ───────────────────────────────────────────────────
                VStack(spacing: 8) {
                    Text("Willkommen bei nahbar")
                        .font(.title.bold())
                        .multilineTextAlignment(.center)
                    Text("Erzähl uns kurz, wer du bist.")
                        .font(.subheadline)
                        .foregroundStyle(.secondary)
                }
                .padding(.top, 48)

                // ── Avatar ───────────────────────────────────────────────────
                avatarSection

                // ── Aus Kontakten importieren ─────────────────────────────────
                Button { showingContactPicker = true } label: {
                    Label("Aus Kontakten ausfüllen", systemImage: "person.crop.circle")
                        .font(.subheadline)
                        .foregroundStyle(Color.accentColor)
                }
                .accessibilityLabel("Eigene Kontaktdaten aus Adressbuch übernehmen")

                // ── Form ─────────────────────────────────────────────────────
                VStack(spacing: 16) {
                    // First name (required)
                    VStack(alignment: .leading, spacing: 6) {
                        Text("Vorname")
                            .font(.caption)
                            .foregroundStyle(.secondary)
                        TextField("z. B. Max", text: $coordinator.firstName)
                            .textFieldStyle(.roundedBorder)
                            .textContentType(.givenName)
                            .submitLabel(.next)
                            .accessibilityLabel("Vorname, erforderlich")
                    }

                    // Display name (optional)
                    VStack(alignment: .leading, spacing: 6) {
                        Text("Spitzname (optional)")
                            .font(.caption)
                            .foregroundStyle(.secondary)
                        TextField("Wie nennen dich deine Freunde?", text: $coordinator.displayName)
                            .textFieldStyle(.roundedBorder)
                            .textContentType(.nickname)
                            .submitLabel(.next)
                            .accessibilityLabel("Spitzname, optional")
                    }

                    // About me (max 100 chars)
                    VStack(alignment: .leading, spacing: 6) {
                        HStack {
                            Text("Über mich (optional)")
                                .font(.caption)
                                .foregroundStyle(.secondary)
                            Spacer()
                            Text("\(coordinator.aboutMe.count)/100")
                                .font(.caption2)
                                .foregroundStyle(coordinator.aboutMe.count > 90 ? Color.orange : Color.secondary.opacity(0.5))
                                .accessibilityLabel("\(coordinator.aboutMe.count) von 100 Zeichen")
                        }
                        TextField(
                            "Wie kennen dich deine Freunde?",
                            text: $coordinator.aboutMe,
                            axis: .vertical
                        )
                        .textFieldStyle(.roundedBorder)
                        .lineLimit(3...5)
                        .onChange(of: coordinator.aboutMe) { _, value in
                            if value.count > 100 {
                                coordinator.aboutMe = String(value.prefix(100))
                            }
                        }
                        .accessibilityLabel("Über mich, maximal 100 Zeichen")
                    }

                    // Geschlecht (optional)
                    VStack(alignment: .leading, spacing: 8) {
                        Text("Geschlecht (optional)")
                            .font(.caption)
                            .foregroundStyle(.secondary)
                        HStack(spacing: 10) {
                            ForEach(["Männlich", "Weiblich", "Divers"], id: \.self) { option in
                                let selected = coordinator.gender == option
                                Button {
                                    let newValue = selected ? "" : option
                                    coordinator.gender = newValue
                                    // Sofort persistieren
                                    UserProfileStore.shared.updateGender(newValue)
                                } label: {
                                    Text(option)
                                        .font(.subheadline)
                                        .padding(.horizontal, 16)
                                        .padding(.vertical, 9)
                                        .background(selected
                                                    ? Color.accentColor.opacity(0.14)
                                                    : Color.secondary.opacity(0.10))
                                        .foregroundStyle(selected ? Color.accentColor : .primary)
                                        .clipShape(Capsule())
                                        .overlay(Capsule().strokeBorder(
                                            selected ? Color.accentColor : Color.clear,
                                            lineWidth: 1.5))
                                }
                                .buttonStyle(.plain)
                                .animation(.easeInOut(duration: 0.15), value: selected)
                                .accessibilityLabel(option)
                                .accessibilityAddTraits(selected ? .isSelected : [])
                            }
                        }
                    }
                }
                .padding(.horizontal, 24)

                // ── Privacy badge ────────────────────────────────────────────
                PrivacyBadgeView(context: .profile)
                    .padding(.horizontal, 24)

                // ── Continue button ──────────────────────────────────────────
                Button {
                    coordinator.advanceToContacts()
                } label: {
                    Text("Weiter")
                        .font(.headline)
                        .frame(maxWidth: .infinity)
                        .padding(.vertical, 14)
                        .background(coordinator.isProfileValid
                                    ? Color.accentColor
                                    : Color.secondary.opacity(0.25))
                        .foregroundStyle(coordinator.isProfileValid ? .white : .secondary)
                        .clipShape(RoundedRectangle(cornerRadius: 12))
                }
                .disabled(!coordinator.isProfileValid)
                .padding(.horizontal, 24)
                .accessibilityLabel("Weiter zu Kontakten")
                .accessibilityHint(coordinator.isProfileValid
                                   ? ""
                                   : "Bitte gib zuerst deinen Vornamen ein.")

                Spacer(minLength: 40)
            }
        }
        .onChange(of: selectedItem) { _, item in
            Task {
                guard let item,
                      let data = try? await item.loadTransferable(type: Data.self),
                      let image = UIImage(data: data) else { return }
                profileImage = image
                UserProfileStore.shared.savePhoto(image)
            }
        }
        .overlay(alignment: .center) {
            SingleContactPickerTrigger(isPresented: $showingContactPicker, onSelect: applyContact)
                .frame(width: 0, height: 0)
                .allowsHitTesting(false)
        }
    }

    private func applyContact(_ contact: CNContact) {
        if !contact.givenName.isEmpty {
            coordinator.firstName = contact.givenName
        }
        // Foto übernehmen, falls vorhanden
        let photoData = contact.thumbnailImageData ?? contact.imageData
        if let data = photoData, let image = UIImage(data: data) {
            profileImage = image
            UserProfileStore.shared.savePhoto(image)
        }
    }

    // MARK: Avatar

    @ViewBuilder
    private var avatarSection: some View {
        ZStack(alignment: .bottomTrailing) {
            // Photo or initials placeholder
            Group {
                if let image = profileImage {
                    Image(uiImage: image)
                        .resizable()
                        .scaledToFill()
                } else {
                    ZStack {
                        Circle()
                            .fill(Color.accentColor.opacity(0.15))
                        Text(initialsPlaceholder)
                            .font(.largeTitle.bold())
                            .foregroundStyle(Color.accentColor)
                    }
                }
            }
            .frame(width: 96, height: 96)
            .clipShape(Circle())

            // Camera button overlay
            PhotosPicker(selection: $selectedItem, matching: .images) {
                Image(systemName: "camera.fill")
                    .font(.caption.weight(.semibold))
                    .foregroundStyle(.white)
                    .padding(7)
                    .background(Color.accentColor)
                    .clipShape(Circle())
            }
            .accessibilityLabel("Profilfoto auswählen")
        }
    }

    private var initialsPlaceholder: String {
        let name = coordinator.firstName.trimmingCharacters(in: .whitespaces)
        guard !name.isEmpty else { return "?" }
        let parts = name.split(separator: " ")
        if parts.count >= 2 {
            return (parts[0].prefix(1) + parts[1].prefix(1)).uppercased()
        }
        return String(name.prefix(2)).uppercased()
    }
}

// MARK: - Phase 2: OnboardingContactImportView

/// Uses CNContactPickerViewController (system picker, no permission needed).
/// Multi-select is activated automatically by implementing didSelectContacts:.
private struct OnboardingContactImportView: View {
    @ObservedObject var coordinator: OnboardingCoordinator
    let onContinue: () -> Void
    let onSkip: () -> Void

    @State private var showingPicker = false
    @State private var showSkipConfirmation: Bool = false

    private let maxContacts = 3
    private var atLimit: Bool { coordinator.selectedContacts.count >= maxContacts }

    var body: some View {
        VStack(spacing: 0) {

            // ── Header ───────────────────────────────────────────────────────
            VStack(spacing: 8) {
                Text("Kontakte hinzufügen")
                    .font(.title.bold())
                    .multilineTextAlignment(.center)
                Text("Wähle bis zu 3 Menschen aus, die dir wichtig sind.")
                    .font(.subheadline)
                    .foregroundStyle(.secondary)
            }
            .padding(.top, 36)
            .padding(.horizontal, 24)

            PrivacyBadgeView(context: .contacts)
                .padding(.horizontal, 16)
                .padding(.top, 16)

            Divider().padding(.top, 16)

            // ── Selected contacts list ────────────────────────────────────────
            if coordinator.selectedContacts.isEmpty {
                emptyPickerPrompt
                    .frame(maxWidth: .infinity, maxHeight: .infinity)
            } else {
                selectedContactsList
                    .frame(maxWidth: .infinity, maxHeight: .infinity)
            }

            Divider()

            // ── Bottom actions ───────────────────────────────────────────────
            VStack(spacing: 10) {
                Button(action: onContinue) {
                    Text(coordinator.selectedContacts.isEmpty
                         ? "Weiter"
                         : "Weiter (\(coordinator.selectedContacts.count) ausgewählt)")
                        .font(.headline)
                        .frame(maxWidth: .infinity)
                        .padding(.vertical, 14)
                        .background(coordinator.selectedContacts.isEmpty
                                    ? Color.secondary.opacity(0.25)
                                    : Color.accentColor)
                        .foregroundStyle(coordinator.selectedContacts.isEmpty ? Color.secondary : Color.white)
                        .clipShape(RoundedRectangle(cornerRadius: 12))
                }
                .disabled(coordinator.selectedContacts.isEmpty)
                .accessibilityLabel(
                    coordinator.selectedContacts.isEmpty
                    ? "Weiter, kein Kontakt ausgewählt"
                    : "\(coordinator.selectedContacts.count) Kontakte ausgewählt. Weiter."
                )

                Button {
                    showSkipConfirmation = true
                } label: {
                    Text("Überspringen")
                        .font(.subheadline)
                        .foregroundStyle(.secondary)
                }
                .accessibilityLabel("Kontakte überspringen")
                .accessibilityHint("Zeigt eine Bestätigungsabfrage.")
            }
            .padding(.horizontal, 24)
            .padding(.vertical, 16)
        }

        .confirmationDialog(
            "Kontakte überspringen?",
            isPresented: $showSkipConfirmation,
            titleVisibility: .visible
        ) {
            Button("Trotzdem überspringen", role: .destructive, action: onSkip)
            Button("Abbrechen", role: .cancel) {}
        } message: {
            Text("Du kannst Kontakte jederzeit später in der App hinzufügen.")
        }
        .overlay(alignment: .center) {
            // Invisible trigger — finds the hosting UIViewController via
            // the UIKit responder chain and presents the system contact picker.
            MultiContactPickerTrigger(isPresented: $showingPicker, onSelect: mergeContacts)
                .frame(width: 0, height: 0)
                .allowsHitTesting(false)
        }
    }

    // MARK: Empty prompt

    private var emptyPickerPrompt: some View {
        VStack(spacing: 20) {
            Spacer()
            Image(systemName: "person.2.badge.plus")
                .font(.system(size: 56))
                .foregroundStyle(Color.accentColor)
                .accessibilityHidden(true)
            Text("Noch keine Kontakte")
                .font(.title3.bold())
            Text("Wähle bis zu 3 Menschen aus deinem Adressbuch, die dir wichtig sind.")
                .font(.subheadline)
                .foregroundStyle(.secondary)
                .multilineTextAlignment(.center)
                .padding(.horizontal, 32)
            Button { showingPicker = true } label: {
                Label("Kontakte auswählen", systemImage: "person.crop.circle.badge.plus")
                    .font(.headline)
                    .frame(maxWidth: .infinity)
                    .padding(.vertical, 14)
                    .background(Color.accentColor)
                    .foregroundStyle(.white)
                    .clipShape(RoundedRectangle(cornerRadius: 12))
                    .padding(.horizontal, 32)
            }
            .accessibilityLabel("Kontakte aus Adressbuch auswählen")
            Spacer()
        }
        .padding()
    }

    // MARK: Selected contacts list

    private var selectedContactsList: some View {
        List {
            Section {
                ForEach(coordinator.selectedContacts) { contact in
                    HStack(spacing: 12) {
                        // Initials avatar
                        ZStack {
                            Circle().fill(Color.accentColor.opacity(0.15))
                            Text(contact.initials)
                                .font(.caption.bold())
                                .foregroundStyle(Color.accentColor)
                        }
                        .frame(width: 36, height: 36)

                        Text(contact.fullName)
                            .font(.body)

                        Spacer()
                    }
                }
                .onDelete { indexSet in
                    coordinator.selectedContacts.remove(atOffsets: indexSet)
                }
            } header: {
                HStack {
                    Text(atLimit
                         ? "\(coordinator.selectedContacts.count) von \(maxContacts) — Maximum erreicht"
                         : "\(coordinator.selectedContacts.count) von \(maxContacts) ausgewählt")
                    Spacer()
                    if !atLimit {
                        Button {
                            showingPicker = true
                        } label: {
                            Label("Weitere hinzufügen", systemImage: "plus")
                                .font(.caption.weight(.medium))
                        }
                    }
                }
            }
        }
        .listStyle(.plain)
    }

    // MARK: Merge helper

    /// Merges newly picked contacts into the existing selection (no duplicates).
    private func mergeContacts(_ contacts: [CNContact]) {
        for contact in contacts {
            guard coordinator.selectedContacts.count < maxContacts else { break }
            let alreadySelected = coordinator.selectedContacts
                .contains { $0.cnIdentifier == contact.identifier }
            if !alreadySelected {
                coordinator.selectedContacts.append(NahbarContact(from: contact))
            }
        }
    }
}

// MARK: - Phase 3: OnboardingPrivacyView

/// Final onboarding screen. Explains the app's privacy-first approach and
/// informs users that AI features are optional and involve a third-party service.
private struct OnboardingPrivacyView: View {
    let onFinish: () -> Void

    var body: some View {
        ZStack {
            Color(.systemBackground)
                .ignoresSafeArea()

            ScrollView {
                VStack(spacing: 32) {

                    // ── Icon ───────────────────────────────────────────────
                    Image(systemName: "lock.shield.fill")
                        .font(.system(size: 72))
                        .foregroundStyle(.green)
                        .padding(.top, 60)
                        .accessibilityHidden(true)

                    // ── Headline ──────────────────────────────────────────
                    VStack(spacing: 10) {
                        Text("Deine Daten gehören dir")
                            .font(.title.bold())
                            .multilineTextAlignment(.center)
                        Text("Alles, was du in nahbar eingibst, wird ausschließlich auf deinem iPhone gespeichert und verarbeitet.")
                            .font(.body)
                            .foregroundStyle(.secondary)
                            .multilineTextAlignment(.center)
                    }
                    .padding(.horizontal, 32)

                    // ── Detail rows ───────────────────────────────────────
                    VStack(alignment: .leading, spacing: 20) {
                        privacyRow(
                            icon: "iphone",
                            text: "Kontakte und Momente bleiben lokal auf deinem Gerät – keine Cloud-Synchronisation."
                        )
                        privacyRow(
                            icon: "person.slash",
                            text: "Keine Registrierung, kein Account, kein Tracking."
                        )
                        privacyRow(
                            icon: "sparkles",
                            text: "KI-Funktionen sind optional. Du entscheidest, wann du sie verwendest. Erst dann werden Daten an einen Drittanbieter übertragen."
                        )
                    }
                    .padding(.horizontal, 24)

                    // ── CTA button ────────────────────────────────────────
                    Button(action: onFinish) {
                        Text("Verstanden & App starten")
                            .font(.headline)
                            .frame(maxWidth: .infinity)
                            .padding(.vertical, 14)
                            .background(Color.accentColor)
                            .foregroundStyle(.white)
                            .clipShape(RoundedRectangle(cornerRadius: 12))
                    }
                    .padding(.horizontal, 24)
                    .accessibilityLabel("Onboarding abschließen und App starten")

                    Spacer(minLength: 40)
                }
            }
        }
    }

    private func privacyRow(icon: String, text: LocalizedStringKey) -> some View {
        HStack(alignment: .top, spacing: 16) {
            Image(systemName: icon)
                .font(.title3)
                .foregroundStyle(Color.accentColor)
                .frame(width: 32)
                .accessibilityHidden(true)
            Text(text)
                .font(.body)
                .foregroundStyle(.primary)
                .fixedSize(horizontal: false, vertical: true)
        }
    }
}

// MARK: - Phase 3: FeatureTourView

/// Data for a single coach-mark card.
struct FeatureTourStep {
    let icon: String
    let title: LocalizedStringKey
    let description: LocalizedStringKey
    let showPrivacySummary: Bool

    static let all: [FeatureTourStep] = [
        FeatureTourStep(
            icon: "checklist",
            title: "Unternehmung",
            description: "Plane Unternehmungen mit Erinnerung – nahbar erinnert dich zur richtigen Zeit.",
            showPrivacySummary: false
        ),
        FeatureTourStep(
            icon: "figure.walk.arrival",
            title: "Treffen",
            description: "Erfasse Treffen als Moment und bewerte sie mit einem kurzen Fragebogen.",
            showPrivacySummary: false
        ),
        FeatureTourStep(
            icon: "square.and.arrow.up",
            title: "Nachrichten importieren",
            description: "Teile WhatsApp-Nachrichten direkt in nahbar – sie werden als Momente gespeichert.",
            showPrivacySummary: false
        ),
        FeatureTourStep(
            icon: "bell.badge",
            title: "Erinnerungen",
            description: "nahbar erinnert dich, wenn du lange nichts von jemandem gehört hast.",
            showPrivacySummary: true
        )
    ]
}

private struct FeatureTourView: View {
    let onFinish: () -> Void

    @State private var stepIndex: Int = 0

    private var steps: [FeatureTourStep] { FeatureTourStep.all }
    private var step: FeatureTourStep { steps[stepIndex] }
    private var isLastStep: Bool { stepIndex == steps.count - 1 }

    var body: some View {
        VStack {
            Spacer()
            coachCard
                .id(stepIndex)
                .transition(.scale.combined(with: .opacity))
                .padding(.horizontal, 28)
            Spacer()
        }
        .frame(maxWidth: .infinity, maxHeight: .infinity)
    }

    @ViewBuilder
    private var coachCard: some View {
        VStack(spacing: 20) {

            // Progress dots
            HStack(spacing: 6) {
                ForEach(0..<steps.count, id: \.self) { i in
                    Circle()
                        .fill(i == stepIndex ? Color.accentColor : Color.secondary.opacity(0.3))
                        .frame(width: i == stepIndex ? 8 : 6,
                               height: i == stepIndex ? 8 : 6)
                        .animation(.spring(response: 0.3, dampingFraction: 0.7), value: stepIndex)
                }
            }
            .accessibilityLabel("Schritt \(stepIndex + 1) von \(steps.count)")

            // Feature icon
            Image(systemName: step.icon)
                .font(.system(size: 52))
                .foregroundStyle(Color.accentColor)
                .accessibilityHidden(true)

            // Title
            Text(step.title)
                .font(.title2.bold())
                .multilineTextAlignment(.center)

            // Description
            Text(step.description)
                .font(.body)
                .foregroundStyle(.secondary)
                .multilineTextAlignment(.center)

            // Privacy summary – last step only
            if step.showPrivacySummary {
                PrivacyBadgeView(context: .summary)
            }

            // Action button
            Button(action: advance) {
                Text(isLastStep ? "Los geht's" : "Weiter")
                    .font(.headline)
                    .frame(maxWidth: .infinity)
                    .padding(.vertical, 14)
                    .background(Color.accentColor)
                    .foregroundStyle(.white)
                    .clipShape(RoundedRectangle(cornerRadius: 12))
            }
            .accessibilityLabel(isLastStep
                                ? "Los geht's – nahbar starten"
                                : "Weiter zum nächsten Schritt")
        }
        .padding(24)
        .background(.regularMaterial)
        .clipShape(RoundedRectangle(cornerRadius: 20))
        .shadow(color: .black.opacity(0.18), radius: 24, y: 10)
    }

    private func advance() {
        if isLastStep {
            onFinish()
        } else {
            withAnimation(.spring(response: 0.45, dampingFraction: 0.82)) {
                stepIndex += 1
            }
        }
    }
}

// MARK: - Preview

#Preview("Onboarding Container") {
    OnboardingContainerView(onComplete: {})
        .modelContainer(for: [Person.self, Moment.self, PersonPhoto.self], inMemory: true)
}
