import SwiftUI
import SwiftData
import EventKit
import UserNotifications
import OSLog

private let intentionNotificationLogger = Logger(subsystem: "nahbar", category: "IntentionNotification")

struct AddMomentView: View {
    @Environment(\.nahbarTheme) var theme
    @Environment(\.modelContext) var modelContext
    @Environment(\.dismiss) var dismiss

    let person: Person

    /// Wird nach dem Speichern eines Treffen-Moments aufgerufen —
    /// die aufrufende Ansicht kann dann den Rating-Flow öffnen.
    var onMeetingCreated: ((Moment) -> Void)? = nil

    @State private var text = ""
    @State private var selectedType: MomentType = .conversation
    @FocusState private var isFocused: Bool

    // Treffen: Kalender-Integration
    @State private var addToCalendar = false
    @State private var eventDate: Date = {
        let cal = Calendar.current
        let hour = cal.component(.hour, from: Date())
        return cal.date(bySettingHour: hour + 1, minute: 0, second: 0, of: Date()) ?? Date()
    }()
    @State private var eventDuration: Double = 3600 // Sekunden; -1 = Ganztag
    @AppStorage("selectedCalendarID") private var defaultCalendarID: String = ""
    @State private var availableCalendars: [EKCalendar] = []
    @State private var selectedCalendarID: String = ""
    @State private var eventAlarmOffset: Double = -3600 // Sekunden; 0 = keine Erinnerung

    // KI-Gesprächsvorschläge
    @StateObject private var store = StoreManager.shared
    @AppStorage("aiConsentGiven") private var aiConsentGiven = false
    @State private var conversationState: ConversationSuggestionUIState = .idle
    @State private var showConversationPaywall = false
    @State private var showConversationConsent = false
    @State private var insertedSectionKey: String? = nil  // für kurzes Checkmark-Feedback

    // Vorhaben: Erinnerung
    @State private var addReminder = false
    @State private var reminderDate: Date = {
        let tomorrow = Calendar.current.date(byAdding: .day, value: 1, to: Date()) ?? Date()
        return Calendar.current.date(bySettingHour: 9, minute: 0, second: 0, of: tomorrow) ?? tomorrow
    }()

    private var isValid: Bool { !text.trimmingCharacters(in: .whitespaces).isEmpty }
    private var showsCalendarSection: Bool { selectedType != .thought }
    private var showsReminderSection: Bool { selectedType != .thought }

    /// Treffen liegt in der Zukunft → kein Rating-Flow nach dem Speichern.
    private var isFutureMeeting: Bool {
        if addToCalendar { return eventDate > Date() }
        if addReminder   { return reminderDate > Date() }
        return false
    }

    private var placeholder: String {
        switch selectedType {
        case .meeting:
            return isFutureMeeting
                ? "Wo trefft ihr euch?\nWas habt ihr vor?"
                : "Wo habt ihr euch getroffen?\nWas habt ihr unternommen?"
        case .thought:
            return "Welcher Gedanke kam dir in den Sinn?"
        case .intention:    // legacy
            return "Was möchtest du mit dieser Person machen?"
        default:            // .conversation
            return isFutureMeeting
                ? "Worüber wollt ihr reden?\nWas möchtest du ansprechen?"
                : "Was war der Kern des Gesprächs?\nWas möchtest du nicht vergessen?"
        }
    }

    var body: some View {
        NavigationStack {
            ScrollView {
            VStack(alignment: .leading, spacing: 20) {

                // Person-Kontext-Chip
                HStack(spacing: 10) {
                    PersonAvatar(person: person, size: 36)
                    Text(person.name)
                        .font(.system(size: 16, weight: .medium, design: theme.displayDesign))
                        .foregroundStyle(theme.contentPrimary)
                    Spacer()
                    Text(Date(), format: .dateTime.day().month(.abbreviated).locale(Locale(identifier: "de_DE")))
                        .font(.system(size: 13))
                        .foregroundStyle(theme.contentTertiary)
                }
                .padding(.horizontal, 20)
                .padding(.top, 8)

                // Typ-Selektor
                ScrollView(.horizontal, showsIndicators: false) {
                    HStack(spacing: 8) {
                        ForEach(MomentType.allCases, id: \.self) { type in
                            Button {
                                selectedType = type
                            } label: {
                                HStack(spacing: 5) {
                                    Image(systemName: type.icon)
                                        .font(.system(size: 12))
                                    Text(LocalizedStringKey(type.displayName))
                                        .font(.system(size: 13, weight: selectedType == type ? .medium : .regular))
                                }
                                .foregroundStyle(selectedType == type ? theme.accent : theme.contentSecondary)
                                .padding(.horizontal, 12)
                                .padding(.vertical, 7)
                                .background(selectedType == type ? theme.accent.opacity(0.10) : theme.backgroundSecondary)
                                .clipShape(Capsule())
                            }
                        }
                    }
                    .padding(.horizontal, 20)
                }

                // Texteingabe
                ZStack(alignment: .topLeading) {
                    if text.isEmpty {
                        Text(placeholder)
                            .font(.system(size: 16))
                            .foregroundStyle(theme.contentTertiary)
                            .padding(.horizontal, 16)
                            .padding(.vertical, 14)
                            .allowsHitTesting(false)
                    }
                    TextEditor(text: $text)
                        .font(.system(size: 16, design: theme.displayDesign))
                        .foregroundStyle(theme.contentPrimary)
                        .tint(theme.accent)
                        .scrollContentBackground(.hidden)
                        .padding(.horizontal, 12)
                        .padding(.vertical, 10)
                        .focused($isFocused)
                }
                .frame(minHeight: 120)
                .background(theme.surfaceCard)
                .clipShape(RoundedRectangle(cornerRadius: theme.radiusCard))
                .padding(.horizontal, 20)

                // KI-Gesprächsvorschläge (nur bei Treffen)
                if selectedType == .meeting || selectedType == .conversation {
                    conversationSuggestionsSection
                        .transition(.opacity.combined(with: .move(edge: .top)))
                }

                // Treffen: Kalendertermin
                if showsCalendarSection {
                    calendarSection
                        .transition(.opacity.combined(with: .move(edge: .top)))
                }

                // Vorhaben: Erinnerung
                if showsReminderSection {
                    reminderSection
                        .transition(.opacity.combined(with: .move(edge: .top)))
                }

            }
            .animation(.easeInOut(duration: 0.2), value: showsCalendarSection)
            .animation(.easeInOut(duration: 0.2), value: showsReminderSection)
            .animation(.easeInOut(duration: 0.2), value: selectedType)
            .animation(.easeInOut(duration: 0.2), value: addToCalendar)
            .animation(.easeInOut(duration: 0.2), value: addReminder)
            .padding(.bottom, 24)
            } // ScrollView
            .background(theme.backgroundPrimary.ignoresSafeArea())
            .navigationTitle("Moment festhalten")
            .navigationBarTitleDisplayMode(.inline)
            .themedNavBar()
            .toolbar {
                ToolbarItem(placement: .topBarLeading) {
                    Button("Abbrechen") { dismiss() }
                        .foregroundStyle(theme.contentSecondary)
                }
                ToolbarItem(placement: .topBarTrailing) {
                    Button("Speichern") { save() }
                        .font(.system(size: 15, weight: .semibold))
                        .foregroundStyle(isValid ? theme.accent : theme.contentTertiary)
                        .disabled(!isValid)
                }
            }
        }
        .onAppear {
            isFocused = true
            if let cached = AIAnalysisService.shared.loadCachedConversation(for: person) {
                conversationState = .result(cached.asResult, cached.generatedAt)
            }
        }
    }

    // MARK: - Kalender-Sektion (Treffen)

    private var calendarSection: some View {
        VStack(spacing: 0) {
            HStack {
                Image(systemName: "calendar")
                    .font(.system(size: 14))
                    .foregroundStyle(addToCalendar ? theme.accent : theme.contentTertiary)
                Text("Termin anlegen")
                    .font(.system(size: 15))
                    .foregroundStyle(theme.contentPrimary)
                Spacer()
                Toggle("", isOn: $addToCalendar)
                    .tint(theme.accent)
            }
            .padding(.horizontal, 16)
            .padding(.vertical, 12)

            if addToCalendar {
                RowDivider()

                DatePicker(
                    "Wann?",
                    selection: $eventDate,
                    in: Date()...,
                    displayedComponents: [.date, .hourAndMinute]
                )
                .font(.system(size: 15))
                .foregroundStyle(theme.contentPrimary)
                .tint(theme.accent)
                .environment(\.locale, Locale.current)
                .padding(.horizontal, 16)
                .padding(.vertical, 10)

                RowDivider()

                HStack {
                    Text("Dauer")
                        .font(.system(size: 15))
                        .foregroundStyle(theme.contentPrimary)
                    Spacer()
                    Picker("", selection: $eventDuration) {
                        Text("30 Min").tag(1800.0)
                        Text("1 Std").tag(3600.0)
                        Text("2 Std").tag(7200.0)
                        Text("Halbtag").tag(14400.0)
                        Text("Ganztag").tag(-1.0)
                    }
                    .tint(theme.accent)
                }
                .padding(.horizontal, 16)
                .padding(.vertical, 4)

                RowDivider()

                HStack {
                    Image(systemName: "bell")
                        .font(.system(size: 13))
                        .foregroundStyle(eventAlarmOffset != 0 ? theme.accent : theme.contentTertiary)
                    Text("Erinnerung")
                        .font(.system(size: 15))
                        .foregroundStyle(theme.contentPrimary)
                    Spacer()
                    Picker("", selection: $eventAlarmOffset) {
                        Text("Keine").tag(0.0)
                        Text("5 Min vorher").tag(-300.0)
                        Text("15 Min vorher").tag(-900.0)
                        Text("1 Std vorher").tag(-3600.0)
                        Text("1 Tag vorher").tag(-86400.0)
                    }
                    .tint(theme.accent)
                }
                .padding(.horizontal, 16)
                .padding(.vertical, 4)

                if availableCalendars.count > 1 {
                    RowDivider()

                    HStack {
                        Text("Kalender")
                            .font(.system(size: 15))
                            .foregroundStyle(theme.contentPrimary)
                        Spacer()
                        Picker("", selection: $selectedCalendarID) {
                            ForEach(availableCalendars, id: \.calendarIdentifier) { cal in
                                HStack(spacing: 6) {
                                    Circle()
                                        .fill(Color(cgColor: cal.cgColor))
                                        .frame(width: 10, height: 10)
                                    Text(cal.title)
                                }
                                .tag(cal.calendarIdentifier)
                            }
                        }
                        .tint(theme.accent)
                    }
                    .padding(.horizontal, 16)
                    .padding(.vertical, 4)
                }
            }
        }
        .background(theme.surfaceCard)
        .clipShape(RoundedRectangle(cornerRadius: theme.radiusCard))
        .padding(.horizontal, 20)
        .task(id: addToCalendar) {
            guard addToCalendar && availableCalendars.isEmpty else { return }
            let calendars = await CalendarManager.shared.availableCalendars()
            availableCalendars = calendars
            // Vorauswahl: gespeicherter Kalender oder der Standard
            if selectedCalendarID.isEmpty || !calendars.map(\.calendarIdentifier).contains(selectedCalendarID) {
                let globalDefault = defaultCalendarID
                if !globalDefault.isEmpty && calendars.map(\.calendarIdentifier).contains(globalDefault) {
                    selectedCalendarID = globalDefault
                } else {
                    selectedCalendarID = CalendarManager.shared.defaultCalendarIdentifier ?? ""
                }
            }
        }
    }

    // MARK: - Erinnerungs-Sektion (Vorhaben)

    private var reminderSection: some View {
        VStack(spacing: 0) {
            HStack {
                Image(systemName: "bell")
                    .font(.system(size: 14))
                    .foregroundStyle(addReminder ? theme.accent : theme.contentTertiary)
                Text("Erinnerung setzen")
                    .font(.system(size: 15))
                    .foregroundStyle(theme.contentPrimary)
                Spacer()
                Toggle("", isOn: $addReminder)
                    .tint(theme.accent)
            }
            .padding(.horizontal, 16)
            .padding(.vertical, 12)

            if addReminder {
                RowDivider()

                DatePicker(
                    "Wann?",
                    selection: $reminderDate,
                    in: Date()...,
                    displayedComponents: [.date, .hourAndMinute]
                )
                .font(.system(size: 15))
                .foregroundStyle(theme.contentPrimary)
                .tint(theme.accent)
                .environment(\.locale, Locale.current)
                .padding(.horizontal, 16)
                .padding(.vertical, 10)
            }
        }
        .background(theme.surfaceCard)
        .clipShape(RoundedRectangle(cornerRadius: theme.radiusCard))
        .padding(.horizontal, 20)
    }

    // MARK: - Speichern

    private func save() {
        let trimmed = text.trimmingCharacters(in: .whitespaces)
        guard !trimmed.isEmpty else { return }

        let moment = Moment(text: trimmed, type: selectedType, person: person)
        modelContext.insert(moment)
        person.moments?.append(moment)
        person.touch()

        // Erinnerung (lokale Notification) – unabhängig vom Kalendereintrag
        if addReminder {
            moment.reminderDate = reminderDate
            scheduleIntentionReminder(for: moment)
        }

        // Kalendereintrag – für alle planbaren Typen, unabhängig von der Erinnerung
        if addToCalendar {
            moment.createdAt = eventDate
            let dateStr = eventDate.formatted(.dateTime.day().month(.abbreviated).hour().minute())
            let calEntry = LogEntry(
                type: .calendarEvent,
                title: calendarLogTitle(date: dateStr),
                person: person
            )
            modelContext.insert(calEntry)
            person.logEntries?.append(calEntry)
            let momentID = moment.id
            Task { await createAndStoreCalendarEvent(for: momentID, notes: trimmed) }
        }

        do {
            try modelContext.save()
        } catch {
            AppEventLog.shared.record(
                "Fehler beim Speichern des Moments: \(error.localizedDescription)",
                level: .error, category: "Moment"
            )
        }

        // Treffen: Callback für Rating-Flow – nur wenn das Treffen bereits stattgefunden hat
        if selectedType == .meeting && !isFutureMeeting {
            dismiss()
            onMeetingCreated?(moment)
            return
        }

        dismiss()
    }

    /// Titel für den LogEntry-Kalender-Eintrag, abhängig vom Typ.
    private func calendarLogTitle(date: String) -> String {
        switch selectedType {
        case .meeting:
            return String.localizedStringWithFormat(String(localized: "Treffen mit %@ — %@"), person.firstName, date)
        case .conversation:
            return String.localizedStringWithFormat(String(localized: "Gespräch mit %@ — %@"), person.firstName, date)
        default:
            return String.localizedStringWithFormat(String(localized: "Termin mit %@ — %@"), person.firstName, date)
        }
    }

    // MARK: - Vorhaben-Erinnerung

    private func scheduleIntentionReminder(for moment: Moment) {
        let center = UNUserNotificationCenter.current()
        center.requestAuthorization(options: [.alert, .sound]) { granted, error in
            if let error {
                intentionNotificationLogger.error("Berechtigung-Fehler: \(error.localizedDescription)")
            }
            guard granted else {
                intentionNotificationLogger.warning("Notification-Berechtigung abgelehnt – keine Vorhaben-Erinnerung.")
                return
            }

            let content = UNMutableNotificationContent()
            content.title = person.firstName
            content.subtitle = String(localized: "Geplanter Moment")
            content.body = moment.text
            content.sound = .default
            content.userInfo = ["momentID": moment.id.uuidString]

            let components = Calendar.current.dateComponents(
                [.year, .month, .day, .hour, .minute], from: reminderDate
            )
            let trigger = UNCalendarNotificationTrigger(dateMatching: components, repeats: false)
            let request = UNNotificationRequest(
                identifier: "intention-\(moment.id)",
                content: content,
                trigger: trigger
            )
            center.add(request) { error in
                if let error {
                    intentionNotificationLogger.error("Vorhaben-Erinnerung konnte nicht geplant werden: \(error.localizedDescription)")
                } else {
                    intentionNotificationLogger.info("Vorhaben-Erinnerung geplant: \(moment.id.uuidString)")
                }
            }
        }
    }

    // MARK: - EventKit (async via CalendarManager)

    private func createAndStoreCalendarEvent(for momentID: UUID, notes: String) async {
        let isAllDay = eventDuration < 0
        let startDate: Date
        let endDate: Date

        if isAllDay {
            startDate = Calendar.current.startOfDay(for: eventDate)
            endDate = Calendar.current.date(byAdding: .day, value: 1, to: startDate) ?? startDate
        } else {
            startDate = eventDate
            endDate = eventDate.addingTimeInterval(eventDuration)
        }

        let calendarID = selectedCalendarID.isEmpty ? nil : selectedCalendarID
        let title: String
        switch selectedType {
        case .meeting:      title = String.localizedStringWithFormat(String(localized: "Treffen mit %@"), person.firstName)
        case .conversation: title = String.localizedStringWithFormat(String(localized: "Gespräch mit %@"), person.firstName)
        default:            title = String.localizedStringWithFormat(String(localized: "Termin mit %@"), person.firstName)
        }
        let alarmOffset: TimeInterval? = eventAlarmOffset == 0 ? nil : eventAlarmOffset

        if let identifier = await CalendarManager.shared.createEvent(
            title: title,
            notes: notes.isEmpty ? nil : notes,
            startDate: startDate,
            endDate: endDate,
            isAllDay: isAllDay,
            calendarIdentifier: calendarID,
            alarmOffset: alarmOffset
        ) {
            CalendarEventStore.save(momentID: momentID, eventIdentifier: identifier)
        }
    }

    // MARK: - KI-Gesprächsvorschläge

    private var canUseAI: Bool {
        store.isMax || AIAnalysisService.shared.hasFreeQueriesLeft
    }

    private var conversationSuggestionsSection: some View {
        Group {
            switch conversationState {
            case .idle:
                conversationIdleButton
            case .loading:
                conversationLoadingView
            case .result(let result, _):
                conversationResultView(result: result)
            case .error(let message):
                conversationErrorView(message: message)
            case .insufficientData:
                conversationInsufficientDataView
            }
        }
        .background(theme.surfaceCard)
        .clipShape(RoundedRectangle(cornerRadius: theme.radiusCard))
        .padding(.horizontal, 20)
        .sheet(isPresented: $showConversationPaywall) { PaywallView(targeting: .max) }
        .sheet(isPresented: $showConversationConsent) {
            AIConsentSheet {
                aiConsentGiven = true
                Task { await loadConversationSuggestions() }
            }
        }
    }

    private var conversationIdleButton: some View {
        Button {
            guard canUseAI else { showConversationPaywall = true; return }
            if aiConsentGiven {
                Task { await loadConversationSuggestions() }
            } else {
                showConversationConsent = true
            }
        } label: {
            HStack(spacing: 8) {
                Image(systemName: "sparkles")
                    .font(.system(size: 13))
                Text("Gesprächsthemen vorschlagen")
                    .font(.system(size: 14, weight: .medium))
                Spacer()
                if !store.isMax && canUseAI {
                    Text("\(AIAnalysisService.shared.freeQueriesRemaining) gratis")
                        .font(.system(size: 10, weight: .bold))
                        .foregroundStyle(theme.contentTertiary)
                        .padding(.horizontal, 6)
                        .padding(.vertical, 2)
                        .background(theme.backgroundSecondary)
                        .clipShape(Capsule())
                } else {
                    MaxBadge()
                }
            }
            .foregroundStyle(canUseAI ? theme.accent : theme.contentSecondary)
            .padding(.horizontal, 16)
            .padding(.vertical, 12)
        }
        .buttonStyle(.plain)
    }

    private var conversationLoadingView: some View {
        HStack(spacing: 10) {
            ProgressView().tint(theme.accent)
            VStack(alignment: .leading, spacing: 2) {
                Text("Vorschläge werden generiert…")
                    .font(.system(size: 14))
                    .foregroundStyle(theme.contentSecondary)
                Text("Das kann einen Moment dauern.")
                    .font(.system(size: 12))
                    .foregroundStyle(theme.contentTertiary)
            }
        }
        .padding(16)
    }

    private func conversationResultView(result: ConversationSuggestionResult) -> some View {
        VStack(alignment: .leading, spacing: 0) {
            conversationSection(icon: "text.bubble",      title: "Themenvorschläge", sectionKey: "topics", content: result.topics)
            RowDivider()
            conversationSection(icon: "lifepreserver",    title: "Gesprächsretter",  sectionKey: "rescue", content: result.rescue)
            RowDivider()
            conversationSection(icon: "arrow.down.heart", title: "Tiefe erreichen",  sectionKey: "depth",  content: result.depth)
            RowDivider()
            Button {
                Task { await loadConversationSuggestions() }
            } label: {
                HStack(spacing: 4) {
                    Image(systemName: "arrow.clockwise").font(.system(size: 12))
                    Text("Neue Vorschläge").font(.system(size: 13))
                }
                .foregroundStyle(theme.accent)
                .padding(.horizontal, 16)
                .padding(.vertical, 10)
            }
        }
    }

    private func conversationSection(icon: String, title: String, sectionKey: String, content: String) -> some View {
        HStack(alignment: .top, spacing: 12) {
            Image(systemName: icon)
                .font(.system(size: 13))
                .foregroundStyle(theme.accent)
                .frame(width: 20)
                .padding(.top, 2)
            VStack(alignment: .leading, spacing: 6) {
                Text(LocalizedStringKey(title))
                    .font(.system(size: 13, weight: .semibold))
                    .foregroundStyle(theme.contentSecondary)
                Text(content)
                    .font(.system(size: 14, design: theme.displayDesign))
                    .foregroundStyle(theme.contentPrimary)
                    .fixedSize(horizontal: false, vertical: true)
            }
            Spacer(minLength: 8)
            // Übernehmen-Button
            Button {
                appendSuggestion(content, key: sectionKey)
            } label: {
                Image(systemName: insertedSectionKey == sectionKey ? "checkmark" : "arrow.up.doc")
                    .font(.system(size: 13))
                    .foregroundStyle(insertedSectionKey == sectionKey ? theme.accent : theme.contentTertiary)
                    .frame(width: 28, height: 28)
                    .contentShape(Rectangle())
                    .animation(.easeInOut(duration: 0.2), value: insertedSectionKey)
            }
            .buttonStyle(.plain)
            .padding(.top, 2)
        }
        .padding(.horizontal, 16)
        .padding(.vertical, 12)
    }

    private func appendSuggestion(_ content: String, key: String) {
        let prefix = text.isEmpty ? "" : "\n\n"
        text += prefix + content
        withAnimation { insertedSectionKey = key }
        DispatchQueue.main.asyncAfter(deadline: .now() + 1.5) {
            withAnimation { insertedSectionKey = nil }
        }
    }

    private var conversationInsufficientDataView: some View {
        HStack(spacing: 10) {
            Image(systemName: "info.circle")
                .font(.system(size: 14))
                .foregroundStyle(theme.contentTertiary)
            Text("Noch zu wenig Verlauf für persönliche Vorschläge.")
                .font(.system(size: 14))
                .foregroundStyle(theme.contentSecondary)
        }
        .padding(16)
    }

    private func conversationErrorView(message: String) -> some View {
        VStack(alignment: .leading, spacing: 8) {
            Label("Vorschläge fehlgeschlagen", systemImage: "exclamationmark.triangle")
                .font(.system(size: 14, weight: .medium))
                .foregroundStyle(theme.contentSecondary)
            Text(message)
                .font(.system(size: 12))
                .foregroundStyle(theme.contentTertiary)
            Button {
                Task { await loadConversationSuggestions() }
            } label: {
                Text("Erneut versuchen")
                    .font(.system(size: 13, weight: .medium))
                    .foregroundStyle(theme.accent)
            }
        }
        .padding(16)
    }

    /// Mindestanzahl an Momenten + Log-Einträgen für sinnvolle KI-Vorschläge.
    private var hasEnoughHistory: Bool {
        let momentCount   = person.sortedMoments.count
        let logCount      = person.sortedLogEntries.count
        return momentCount + logCount >= 2
    }

    private func loadConversationSuggestions() async {
        guard hasEnoughHistory else {
            conversationState = .insufficientData
            return
        }
        guard !AIAnalysisService.shared.isRateLimited else { return }
        conversationState = .loading
        do {
            let result = try await AIAnalysisService.shared.suggestConversation(person: person)
            if !store.isMax { AIAnalysisService.shared.consumeFreeQuery() }
            conversationState = .result(result, Date())
        } catch {
            if let cached = AIAnalysisService.shared.loadCachedConversation(for: person) {
                conversationState = .result(cached.asResult, cached.generatedAt)
            } else {
                conversationState = .error(error.localizedDescription)
            }
        }
    }
}

// MARK: - Conversation Suggestion UI State

private enum ConversationSuggestionUIState {
    case idle
    case loading
    case result(ConversationSuggestionResult, Date)
    case error(String)
    case insufficientData
}

extension ConversationSuggestionUIState: Equatable {
    static func == (lhs: ConversationSuggestionUIState, rhs: ConversationSuggestionUIState) -> Bool {
        switch (lhs, rhs) {
        case (.idle, .idle), (.loading, .loading), (.insufficientData, .insufficientData): return true
        case (.error(let a), .error(let b)): return a == b
        default:                             return false
        }
    }
}
