import SwiftUI
import SwiftData
import CoreData

// MARK: - Timeline Item

private enum LogbuchItem: Identifiable {
    case moment(Moment)
    case logEntry(LogEntry)

    var id: String {
        switch self {
        case .moment(let m):   return "m-\(m.id)"
        case .logEntry(let e): return "e-\(e.id)"
        }
    }

    var date: Date {
        switch self {
        case .moment(let m):   return m.createdAt
        case .logEntry(let e): return e.loggedAt
        }
    }

    var icon: String {
        switch self {
        case .moment(let m):   return m.type.icon
        case .logEntry(let e): return e.type.icon
        }
    }

    var label: String {
        switch self {
        case .moment(let m):   return m.type.displayName
        case .logEntry(let e): return e.type.rawValue
        }
    }

    var title: String {
        switch self {
        case .moment(let m):   return m.text
        case .logEntry(let e): return e.title
        }
    }

    var isLogEntry: Bool {
        if case .logEntry = self { return true }
        return false
    }
}

// MARK: - Logbuch View

struct LogbuchView: View {
    @Environment(\.nahbarTheme) var theme
    @Environment(\.modelContext) var modelContext
    @Environment(\.dismiss) var dismiss
    let person: Person

    // Kalender-Lösch-Bestätigung
    @State private var momentPendingDelete: Moment? = nil
    @State private var showCalendarDeleteDialog = false

    // Moment-Bearbeitung
    @State private var momentForTextEdit: Moment? = nil

    /// Inkrementiert bei jeder CalendarEventStore-Änderung → triggert Re-Render der Rows.
    @State private var calendarEventsVersion = 0

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

                // Timeline
                if mergedItems.isEmpty {
                    emptyState
                } else {
                    ForEach(groupedItems, id: \.0) { month, items in
                        monthSection(month: month, items: items)
                    }
                }

            }
            .padding(.horizontal, 20)
            .padding(.top, 16)
            .padding(.bottom, 48)
        }
        .background(theme.backgroundPrimary.ignoresSafeArea())
        .navigationTitle("Logbuch")
        .navigationBarTitleDisplayMode(.inline)
        .themedNavBar()
        .sheet(item: $momentForTextEdit) { moment in
            EditMomentView(moment: moment)
        }
        .onReceive(NotificationCenter.default.publisher(for: CalendarEventStore.didChangeNotification)) { _ in
            calendarEventsVersion += 1
        }
        .confirmationDialog(
            "Moment löschen",
            isPresented: $showCalendarDeleteDialog,
            presenting: momentPendingDelete
        ) { moment in
            Button("Moment + Kalendereintrag löschen", role: .destructive) {
                performDelete(moment, deleteCalendarEvent: true)
                momentPendingDelete = nil
            }
            Button("Nur Moment löschen", role: .destructive) {
                performDelete(moment, deleteCalendarEvent: false)
                momentPendingDelete = nil
            }
            Button("Abbrechen", role: .cancel) {
                momentPendingDelete = nil
            }
        } message: { _ in
            Text("Dieser Moment hat einen verknüpften Kalendereintrag. Soll dieser ebenfalls gelöscht werden?")
        }
        .onReceive(
            NotificationCenter.default.publisher(
                for: Notification.Name("NSManagedObjectContextObjectsDidChangeNotification")
            )
        ) { notification in
            guard notification.userInfo?[NSInvalidatedAllObjectsKey] != nil else { return }
            dismiss()
        }
    }

    // MARK: - Month Section

    private func monthSection(month: String, items: [LogbuchItem]) -> some View {
        VStack(alignment: .leading, spacing: 10) {
            Text(month.uppercased())
                .font(.system(size: 11, weight: .semibold))
                .tracking(0.8)
                .foregroundStyle(theme.contentTertiary)

            VStack(spacing: 0) {
                ForEach(Array(items.enumerated()), id: \.element.id) { index, item in
                    if case .moment(let moment) = item {
                        DeletableLogbuchRow(
                            isImportant: moment.isImportant,
                            isLast: index == items.count - 1,
                            onEdit: { momentForTextEdit = moment },
                            onDelete: { deleteMoment(moment) },
                            onToggleImportant: { toggleImportant(moment) }
                        ) {
                            logbuchRow(item: item)
                        }
                    } else {
                        logbuchRow(item: item)
                        if index < items.count - 1 { RowDivider() }
                    }
                }
            }
            .background(theme.surfaceCard)
            .clipShape(RoundedRectangle(cornerRadius: theme.radiusCard))
        }
    }

    private func deleteMoment(_ moment: Moment) {
        if CalendarEventStore.identifier(for: moment.id) != nil {
            momentPendingDelete = moment
            showCalendarDeleteDialog = true
        } else {
            performDelete(moment, deleteCalendarEvent: false)
        }
    }

    private func performDelete(_ moment: Moment, deleteCalendarEvent: Bool) {
        let momentID = moment.id
        if deleteCalendarEvent, let eventID = CalendarEventStore.identifier(for: momentID) {
            Task {
                _ = await CalendarManager.shared.deleteEvent(identifier: eventID)
                CalendarEventStore.remove(momentID: momentID)
            }
        } else {
            CalendarEventStore.remove(momentID: momentID)
        }
        modelContext.delete(moment)
        person.touch()
    }

    private func toggleImportant(_ moment: Moment) {
        moment.isImportant.toggle()
        moment.updatedAt = Date()
    }

    // MARK: - Row

    private func logbuchRow(item: LogbuchItem) -> some View {
        HStack(alignment: .top, spacing: 12) {
            // Typ-Icon (bei Vorhaben: Checkbox-Status)
            Group {
                if case .moment(let m) = item, m.isIntention {
                    Image(systemName: m.isCompleted ? "checkmark.circle.fill" : "circle")
                        .foregroundStyle(m.isCompleted ? Color.green : theme.contentTertiary)
                } else {
                    Image(systemName: item.icon)
                        .foregroundStyle(item.isLogEntry ? theme.accent : theme.contentTertiary)
                }
            }
            .font(.system(size: 14, weight: .light))
            .frame(width: 20)
            .padding(.top, 2)

            VStack(alignment: .leading, spacing: 3) {
                // Titel (Vorhaben: Durchgestrichen wenn erledigt)
                if case .moment(let m) = item, m.isIntention, m.isCompleted {
                    Text(item.title)
                        .font(.system(size: 15, design: theme.displayDesign))
                        .foregroundStyle(theme.contentTertiary)
                        .strikethrough(true, color: theme.contentTertiary)
                        .fixedSize(horizontal: false, vertical: true)
                } else {
                    Text(item.title)
                        .font(.system(size: 15, design: theme.displayDesign))
                        .foregroundStyle(theme.contentPrimary)
                        .fixedSize(horizontal: false, vertical: true)
                }

                HStack(spacing: 6) {
                    if case .moment(let m) = item, m.isImportant {
                        Image(systemName: "star.fill")
                            .font(.system(size: 10))
                            .foregroundStyle(.orange)
                    }
                    if case .moment(let m) = item,
                       calendarEventsVersion >= 0, // Dependency auf calendarEventsVersion
                       CalendarEventStore.identifier(for: m.id) != nil {
                        Image(systemName: "calendar")
                            .font(.system(size: 10))
                            .foregroundStyle(theme.contentTertiary)
                    }
                    Text(LocalizedStringKey(item.label))
                        .font(.system(size: 12))
                        .foregroundStyle(theme.contentTertiary)
                    Text("·")
                        .font(.system(size: 12))
                        .foregroundStyle(theme.contentTertiary)
                    Text(item.date.formatted(.dateTime.day().month(.abbreviated).year()))
                        .font(.system(size: 12))
                        .foregroundStyle(theme.contentTertiary)
                }
            }

            Spacer()

            // Score-Badge für bewertete Treffen
            if case .moment(let m) = item, m.isMeeting, let avg = m.immediateAverage {
                ZStack {
                    Circle()
                        .fill(scoreColor(avg).opacity(0.15))
                        .frame(width: 30, height: 30)
                    Text(String(format: "%.1f", avg))
                        .font(.system(size: 9, weight: .bold))
                        .foregroundStyle(scoreColor(avg))
                }
                .padding(.top, 2)
            }
        }
        .padding(.horizontal, 16)
        .padding(.vertical, 12)
    }

    private func scoreColor(_ value: Double) -> Color {
        switch value {
        case ..<(-0.5): return .red
        case (-0.5)..<(0.5): return Color(.systemGray3)
        case (0.5)...: return .green
        default: return .gray
        }
    }

    // MARK: - Empty State

    private var emptyState: some View {
        VStack(spacing: 8) {
            Image(systemName: "book.closed")
                .font(.system(size: 32, weight: .light))
                .foregroundStyle(theme.contentTertiary)
            Text("Noch keine Einträge")
                .font(.system(size: 16, weight: .light))
                .foregroundStyle(theme.contentSecondary)
            Text("Momente und abgeschlossene Schritte erscheinen hier.")
                .font(.system(size: 14))
                .foregroundStyle(theme.contentTertiary)
                .multilineTextAlignment(.center)
        }
        .frame(maxWidth: .infinity)
        .padding(.vertical, 48)
    }

    // MARK: - Data

    private var mergedItems: [LogbuchItem] {
        let moments  = person.sortedMoments.map  { LogbuchItem.moment($0) }
        let entries  = person.sortedLogEntries.map { LogbuchItem.logEntry($0) }
        return (moments + entries).sorted { $0.date > $1.date }
    }

    private var groupedItems: [(String, [LogbuchItem])] {
        let formatter = DateFormatter()
        formatter.dateFormat = "MMMM yyyy"
        formatter.locale = Locale.current

        var result: [(String, [LogbuchItem])] = []
        var currentKey = ""
        var currentGroup: [LogbuchItem] = []

        for item in mergedItems {
            let key = formatter.string(from: item.date)
            if key != currentKey {
                if !currentGroup.isEmpty { result.append((currentKey, currentGroup)) }
                currentKey = key
                currentGroup = [item]
            } else {
                currentGroup.append(item)
            }
        }
        if !currentGroup.isEmpty { result.append((currentKey, currentGroup)) }
        return result
    }
}

// MARK: - Deletable Logbuch Row
// Rechts wischen → Bearbeiten (accent) + Wichtig (orange), Links wischen → Löschen (rot)

private struct DeletableLogbuchRow<Content: View>: View {
    @Environment(\.nahbarTheme) var theme
    let isImportant: Bool
    let isLast: Bool
    let onEdit: () -> Void
    let onDelete: () -> Void
    let onToggleImportant: () -> Void
    @ViewBuilder let content: Content

    @State private var offset: CGFloat = 0
    private let actionWidth: CGFloat = 76

    var body: some View {
        ZStack {
            HStack(spacing: 0) {
                // Links: Bearbeiten-Button
                Button {
                    withAnimation(.spring(response: 0.32, dampingFraction: 0.8)) { offset = 0 }
                    onEdit()
                } label: {
                    VStack(spacing: 4) {
                        Image(systemName: "pencil")
                            .font(.system(size: 15, weight: .medium))
                        Text("Bearbeiten")
                            .font(.system(size: 11, weight: .medium))
                    }
                    .foregroundStyle(.white)
                    .frame(width: actionWidth)
                    .frame(maxHeight: .infinity)
                }
                .background(theme.accent)

                // Links: Wichtig-Button
                Button {
                    onToggleImportant()
                    withAnimation(.spring(response: 0.32, dampingFraction: 0.8)) { offset = 0 }
                } label: {
                    VStack(spacing: 4) {
                        Image(systemName: isImportant ? "star.slash.fill" : "star.fill")
                            .font(.system(size: 15, weight: .medium))
                        Text(isImportant ? "Entfernen" : "Wichtig")
                            .font(.system(size: 11, weight: .medium))
                    }
                    .foregroundStyle(.white)
                    .frame(width: actionWidth)
                    .frame(maxHeight: .infinity)
                }
                .background(Color.orange)

                Spacer()

                // Rechts: Löschen-Button
                Button {
                    withAnimation(.spring(response: 0.28, dampingFraction: 0.75)) {
                        offset = -UIScreen.main.bounds.width
                    }
                    DispatchQueue.main.asyncAfter(deadline: .now() + 0.25) { onDelete() }
                } label: {
                    VStack(spacing: 4) {
                        Image(systemName: "trash")
                            .font(.system(size: 15, weight: .medium))
                        Text("Löschen")
                            .font(.system(size: 11, weight: .medium))
                    }
                    .foregroundStyle(.white)
                    .frame(width: actionWidth)
                    .frame(maxHeight: .infinity)
                }
                .background(Color.red)
            }

            VStack(spacing: 0) {
                content
                if !isLast { RowDivider() }
            }
            .background(theme.surfaceCard)
            .offset(x: offset)
            .gesture(
                DragGesture(minimumDistance: 50, coordinateSpace: .local)
                    .onChanged { value in
                        let x = value.translation.width
                        let y = value.translation.height
                        guard abs(x) > abs(y) * 2.5 else { return }
                        if x > 0 {
                            offset = min(x, actionWidth * 2 + 16)
                        } else {
                            offset = max(x, -(actionWidth + 16))
                        }
                    }
                    .onEnded { value in
                        let x = value.translation.width
                        let y = value.translation.height
                        guard abs(x) > abs(y) * 2.5 else {
                            withAnimation(.spring(response: 0.32, dampingFraction: 0.8)) { offset = 0 }
                            return
                        }
                        if x > actionWidth * 2 + 20 {
                            onToggleImportant()
                            withAnimation(.spring(response: 0.32, dampingFraction: 0.8)) { offset = 0 }
                        } else if x > actionWidth * 1.5 {
                            withAnimation(.spring(response: 0.32, dampingFraction: 0.8)) { offset = actionWidth * 2 }
                        } else if x < -(actionWidth * 1.5) {
                            withAnimation(.spring(response: 0.32, dampingFraction: 0.8)) { offset = -actionWidth }
                        } else {
                            withAnimation(.spring(response: 0.32, dampingFraction: 0.8)) { offset = 0 }
                        }
                    }
            )
        }
        .clipped()
    }
}
