import SwiftUI
import ComposeApp

struct AllTasksView: View {
    @StateObject private var taskViewModel = TaskViewModel()
    @StateObject private var residenceViewModel = ResidenceViewModel()
    @StateObject private var subscriptionCache = SubscriptionCacheWrapper.shared
    @State private var showAddTask = false
    @State private var showingUpgradePrompt = false
    @State private var selectedTaskForEdit: TaskResponse?
    @State private var selectedTaskForComplete: TaskResponse?

    @State private var selectedTaskForArchive: TaskResponse?
    @State private var showArchiveConfirmation = false

    @State private var selectedTaskForCancel: TaskResponse?
    @State private var showCancelConfirmation = false

    @State private var pendingTaskId: Int32?
    @State private var scrollToColumnIndex: Int?

    // Completion animation state
    @StateObject private var animationPreference = AnimationPreference.shared
    @State private var animatingTaskId: Int32? = nil
    @State private var animationPhase: AnimationPhase = .idle
    @State private var pendingCompletedTask: TaskResponse? = nil
    @Environment(\.accessibilityReduceMotion) private var reduceMotion

    private var totalTaskCount: Int { taskViewModel.totalTaskCount }
    private var hasNoTasks: Bool { taskViewModel.hasNoTasks }
    private var hasTasks: Bool { taskViewModel.hasTasks }
    private var tasksResponse: TaskColumnsResponse? { taskViewModel.tasksResponse }
    private var isLoadingTasks: Bool { taskViewModel.isLoadingTasks }
    private var tasksError: String? { taskViewModel.tasksError }

    private var shouldShowSwipeHint: Bool {
        guard let response = tasksResponse,
              let firstColumn = response.columns.first else { return false }
        let hasTasksInOtherColumns = response.columns.dropFirst().contains { !$0.tasks.isEmpty }
        return firstColumn.tasks.isEmpty && hasTasksInOtherColumns
    }

    var body: some View {
        mainContent
            .sheet(isPresented: $showAddTask) {
                AddTaskWithResidenceView(
                    isPresented: $showAddTask,
                    residences: residenceViewModel.myResidences?.residences ?? []
                )
            }
            .sheet(item: $selectedTaskForEdit) { task in
                EditTaskView(task: task, isPresented: Binding(
                    get: { selectedTaskForEdit != nil },
                    set: { if !$0 { selectedTaskForEdit = nil } }
                ))
            }
            .sheet(item: $selectedTaskForComplete, onDismiss: {
                if let task = pendingCompletedTask {
                    startCompletionAnimation(for: task)
                } else {
                    // Delay clearing animation state so the sheet dismissal
                    // animation finishes before data refreshes move tasks
                    DispatchQueue.main.asyncAfter(deadline: .now() + 0.3) {
                        taskViewModel.isAnimatingCompletion = false
                        loadAllTasks(forceRefresh: true)
                    }
                }
            }) { task in
                CompleteTaskView(task: task) { updatedTask in
                    if let updatedTask = updatedTask {
                        pendingCompletedTask = updatedTask
                    }
                    selectedTaskForComplete = nil
                }
            }
            .sheet(isPresented: $showingUpgradePrompt) {
                UpgradePromptView(triggerKey: "add_11th_task", isPresented: $showingUpgradePrompt)
            }
            .alert(L10n.Tasks.archiveTask, isPresented: $showArchiveConfirmation) {
                Button(L10n.Common.cancel, role: .cancel) {
                    selectedTaskForArchive = nil
                }
                Button(L10n.Tasks.archive, role: .destructive) {
                    if let task = selectedTaskForArchive {
                        taskViewModel.archiveTask(id: task.id) { _ in
                            loadAllTasks()
                        }
                        selectedTaskForArchive = nil
                    }
                }
            } message: {
                if let task = selectedTaskForArchive {
                    Text(L10n.Tasks.archiveConfirm.replacingOccurrences(of: "this task", with: "\"\(task.title)\""))
                }
            }
            .alert(L10n.Tasks.cancelTask, isPresented: $showCancelConfirmation) {
                Button(L10n.Common.no, role: .cancel) {
                    selectedTaskForCancel = nil
                }
                Button(L10n.Common.yes, role: .destructive) {
                    if let task = selectedTaskForCancel {
                        taskViewModel.cancelTask(id: task.id) { _ in
                            loadAllTasks()
                        }
                        selectedTaskForCancel = nil
                    }
                }
            } message: {
                Text(L10n.Tasks.cancelConfirm)
            }
            .onAppear {
                AnalyticsManager.shared.trackScreen(.tasks)

                if let taskId = PushNotificationManager.shared.pendingNavigationTaskId {
                    pendingTaskId = Int32(taskId)
                }

                if WidgetDataManager.shared.areTasksDirty() {
                    WidgetDataManager.shared.clearDirtyFlag()
                    loadAllTasks(forceRefresh: true)
                } else {
                    loadAllTasks()
                }
                residenceViewModel.loadMyResidences()
            }
            .onReceive(NotificationCenter.default.publisher(for: .navigateToTask)) { notification in
                if let userInfo = notification.userInfo,
                   let taskId = userInfo["taskId"] as? Int {
                    pendingTaskId = Int32(taskId)
                    if let response = tasksResponse {
                        navigateToTaskInKanban(taskId: Int32(taskId), response: response)
                    }
                }
            }
            .onReceive(NotificationCenter.default.publisher(for: .navigateToEditTask)) { notification in
                if let userInfo = notification.userInfo,
                   let taskId = userInfo["taskId"] as? Int {
                    pendingTaskId = Int32(taskId)
                    if let response = tasksResponse {
                        navigateToTaskInKanban(taskId: Int32(taskId), response: response)
                    }
                }
            }
            .onChange(of: tasksResponse) { _, response in
                if let taskId = pendingTaskId, let response = response {
                    navigateToTaskInKanban(taskId: taskId, response: response)
                }
            }
            // P-5: Removed redundant .onChange(of: scenePhase) handler.
            // iOSApp.swift already handles foreground refresh and widget dirty-flag
            // processing globally, so per-view scenePhase handlers fire duplicate
            // network requests.
            .onChange(of: residenceViewModel.myResidences?.residences.count) { _, newCount in
                // Residence list changed (join/leave/create/delete) — reload tasks
                if let count = newCount, count > 0 {
                    loadAllTasks(forceRefresh: true)
                }
            }
    }

    @ViewBuilder
    private var mainContent: some View {
        ZStack {
            WarmGradientBackground()

            if hasNoTasks && isLoadingTasks {
                ProgressView()
            } else if let error = tasksError {
                ErrorView(message: error) {
                    loadAllTasks()
                }
            } else if let tasksResponse = tasksResponse {
                if hasNoTasks {
                    OrganicEmptyTasksView(
                        totalTaskCount: totalTaskCount,
                        hasResidences: !(residenceViewModel.myResidences?.residences.isEmpty ?? true),
                        subscriptionCache: subscriptionCache,
                        showingUpgradePrompt: $showingUpgradePrompt,
                        showAddTask: $showAddTask
                    )
                } else {
                    ScrollViewReader { proxy in
                        ScrollView(.horizontal, showsIndicators: false) {
                            LazyHGrid(rows: [
                                GridItem(.flexible(), spacing: 16)
                            ], spacing: 16) {
                                ForEach(Array(tasksResponse.columns.enumerated()), id: \.element.name) { index, column in
                                    ZStack {
                                        DynamicTaskColumnView(
                                            column: column,
                                            onEditTask: { task in
                                                selectedTaskForEdit = task
                                            },
                                            onCancelTask: { task in
                                                selectedTaskForCancel = task
                                                showCancelConfirmation = true
                                            },
                                            onUncancelTask: { taskId in
                                                taskViewModel.uncancelTask(id: taskId) { _ in
                                                    loadAllTasks()
                                                }
                                            },
                                            onMarkInProgress: { taskId in
                                                taskViewModel.markInProgress(id: taskId) { success in
                                                    if success {
                                                        loadAllTasks()
                                                    }
                                                }
                                            },
                                            onCompleteTask: { task in
                                                // Block DataManager BEFORE sheet opens so the
                                                // API response can't move the task while we wait
                                                taskViewModel.isAnimatingCompletion = true
                                                selectedTaskForComplete = task
                                            },
                                            onArchiveTask: { task in
                                                selectedTaskForArchive = task
                                                showArchiveConfirmation = true
                                            },
                                            onUnarchiveTask: { taskId in
                                                taskViewModel.unarchiveTask(id: taskId) { _ in
                                                    loadAllTasks()
                                                }
                                            },
                                            animatingTaskId: animatingTaskId,
                                            animationPhase: animationPhase,
                                            animationType: animationPreference.selectedAnimation
                                        )

                                        if index == 0 && shouldShowSwipeHint {
                                            SwipeHintView()
                                        }
                                    }
                                    .frame(width: 350)
                                    .id(index)
                                    .scrollTransition { content, phase in
                                        content
                                            .opacity(phase.isIdentity ? 1 : 0.8)
                                            .scaleEffect(phase.isIdentity ? 1 : 0.95)
                                    }
                                }
                            }
                            .scrollTargetLayout()
                            .padding(16)
                        }
                        .scrollTargetBehavior(.viewAligned)
                        .onChange(of: scrollToColumnIndex) { _, columnIndex in
                            if let columnIndex = columnIndex {
                                withAnimation(.easeInOut(duration: 0.3)) {
                                    proxy.scrollTo(columnIndex, anchor: .leading)
                                }
                                DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
                                    scrollToColumnIndex = nil
                                }
                            }
                        }
                    }
                }
            }
        }
        .navigationBarTitleDisplayMode(.inline)
        .toolbar {
            ToolbarItem(placement: .navigationBarTrailing) {
                HStack(spacing: 12) {
                    Button(action: {
                        loadAllTasks(forceRefresh: true)
                    }) {
                        Image(systemName: "arrow.clockwise")
                            .font(.system(size: 14, weight: .semibold))
                            .foregroundColor(Color.appTextSecondary)
                            .rotationEffect(.degrees(isLoadingTasks ? 360 : 0))
                            .animation(isLoadingTasks ? .linear(duration: 0.5).repeatForever(autoreverses: false) : .default, value: isLoadingTasks)
                    }
                    .disabled((residenceViewModel.myResidences?.residences.isEmpty ?? true) || isLoadingTasks)
                    .accessibilityIdentifier(AccessibilityIdentifiers.Task.refreshButton)
                    .accessibilityLabel("Refresh tasks")

                    Button(action: {
                        if subscriptionCache.shouldShowUpgradePrompt(currentCount: totalTaskCount, limitKey: "tasks") {
                            showingUpgradePrompt = true
                        } else {
                            showAddTask = true
                        }
                    }) {
                        OrganicToolbarAddButton()
                    }
                    .disabled((residenceViewModel.myResidences?.residences.isEmpty ?? true) || showAddTask)
                    .accessibilityIdentifier(AccessibilityIdentifiers.Task.addButton)
                    .accessibilityLabel("Add new task")
                }
            }
        }
    }

    private func loadAllTasks(forceRefresh: Bool = false) {
        taskViewModel.loadTasks(forceRefresh: forceRefresh)
    }

    private func updateTaskInKanban(_ updatedTask: TaskResponse) {
        taskViewModel.updateTaskInKanban(updatedTask)
    }

    /// Called after the completion sheet is fully dismissed.
    /// Plays the celebration animation on the card, then moves it to Done.
    private func startCompletionAnimation(for updatedTask: TaskResponse) {
        let duration = animationPreference.animationDuration(reduceMotion: reduceMotion)

        guard duration > 0 else {
            taskViewModel.isAnimatingCompletion = false
            updateTaskInKanban(updatedTask)
            pendingCompletedTask = nil
            return
        }

        animatingTaskId = updatedTask.id

        withAnimation {
            animationPhase = .exiting
        }

        DispatchQueue.main.asyncAfter(deadline: .now() + 0.2) {
            withAnimation {
                animationPhase = .complete
            }
        }

        DispatchQueue.main.asyncAfter(deadline: .now() + duration) {
            taskViewModel.isAnimatingCompletion = false
            updateTaskInKanban(updatedTask)
            animatingTaskId = nil
            animationPhase = .idle
            pendingCompletedTask = nil
        }
    }

    private func navigateToTaskInKanban(taskId: Int32, response: TaskColumnsResponse) {
        for (index, column) in response.columns.enumerated() {
            if let task = column.tasks.first(where: { $0.id == taskId }) {
                pendingTaskId = nil
                PushNotificationManager.shared.clearPendingNavigation()
                DispatchQueue.main.asyncAfter(deadline: .now() + 0.3) {
                    self.scrollToColumnIndex = index
                }
                // Open the edit sheet for this task so the user sees its details
                DispatchQueue.main.asyncAfter(deadline: .now() + 0.6) {
                    self.selectedTaskForEdit = task
                }
                return
            }
        }
        pendingTaskId = nil
        PushNotificationManager.shared.clearPendingNavigation()
    }
}

// MARK: - Organic Empty Tasks View

private struct OrganicEmptyTasksView: View {
    let totalTaskCount: Int
    let hasResidences: Bool
    let subscriptionCache: SubscriptionCacheWrapper
    @Binding var showingUpgradePrompt: Bool
    @Binding var showAddTask: Bool
    @State private var isAnimating = false
    @Environment(\.accessibilityReduceMotion) private var reduceMotion

    var body: some View {
        VStack(spacing: OrganicSpacing.comfortable) {
            Spacer()

            ZStack {
                Circle()
                    .fill(
                        RadialGradient(
                            colors: [
                                Color.appPrimary.opacity(0.15),
                                Color.appPrimary.opacity(0.05),
                                Color.clear
                            ],
                            center: .center,
                            startRadius: 0,
                            endRadius: 80
                        )
                    )
                    .frame(width: 160, height: 160)
                    .scaleEffect(isAnimating ? 1.1 : 1.0)
                    .animation(
                        isAnimating && !reduceMotion
                            ? Animation.easeInOut(duration: 3).repeatForever(autoreverses: true)
                            : .default,
                        value: isAnimating
                    )

                ZStack {
                    Circle()
                        .fill(Color.appPrimary.opacity(0.1))
                        .frame(width: 100, height: 100)

                    Image(systemName: "checklist")
                        .font(.system(size: 44, weight: .medium))
                        .foregroundColor(Color.appPrimary)
                        .offset(y: isAnimating ? -2 : 2)
                        .animation(
                            isAnimating && !reduceMotion
                                ? Animation.easeInOut(duration: 2).repeatForever(autoreverses: true)
                                : .default,
                            value: isAnimating
                        )
                }
            }

            VStack(spacing: 12) {
                Text(L10n.Tasks.noTasksYet)
                    .font(.system(size: 24, weight: .bold, design: .rounded))
                    .foregroundColor(Color.appTextPrimary)

                Text(L10n.Tasks.createFirst)
                    .font(.system(size: 15, weight: .medium))
                    .foregroundColor(Color.appTextSecondary)
                    .multilineTextAlignment(.center)
                    .lineSpacing(4)
            }
            .padding(.top, 8)

            Button(action: {
                if subscriptionCache.shouldShowUpgradePrompt(currentCount: totalTaskCount, limitKey: "tasks") {
                    showingUpgradePrompt = true
                } else {
                    showAddTask = true
                }
            }) {
                HStack(spacing: 10) {
                    Image(systemName: "plus")
                        .font(.system(size: 16, weight: .bold))
                    Text(L10n.Tasks.addButton)
                        .font(.system(size: 17, weight: .semibold))
                }
                .foregroundColor(hasResidences ? Color.appTextOnPrimary : Color.appTextSecondary)
                .frame(maxWidth: .infinity)
                .frame(height: 56)
                .background(
                    hasResidences
                        ? AnyShapeStyle(LinearGradient(
                            colors: [Color.appPrimary, Color.appPrimary.opacity(0.85)],
                            startPoint: .topLeading,
                            endPoint: .bottomTrailing
                        ))
                        : AnyShapeStyle(Color.appTextSecondary.opacity(0.3))
                )
                .clipShape(RoundedRectangle(cornerRadius: 16, style: .continuous))
                .shadow(color: hasResidences ? Color.appPrimary.opacity(0.3) : Color.clear, radius: 12, y: 6)
            }
            .disabled(!hasResidences)
            .padding(.horizontal, 48)
            .padding(.top, 16)
            .accessibilityIdentifier(AccessibilityIdentifiers.Task.addButton)

            if !hasResidences {
                Text(L10n.Tasks.addPropertyFirst)
                    .font(.system(size: 13, weight: .medium))
                    .foregroundColor(Color.appError)
            }

            Spacer()

            HStack(spacing: 40) {
                FloatingLeaf(delay: 0, size: 18, color: Color.appPrimary)
                FloatingLeaf(delay: 0.5, size: 14, color: Color.appAccent)
                FloatingLeaf(delay: 1.0, size: 20, color: Color.appPrimary)
            }
            .opacity(0.6)
            .padding(.bottom, 40)
        }
        .frame(maxWidth: .infinity, maxHeight: .infinity)
        .onAppear {
            isAnimating = true
        }
        .onDisappear {
            isAnimating = false
        }
    }
}

// MARK: - Organic Toolbar Add Button

private struct OrganicToolbarAddButton: View {
    var body: some View {
        ZStack {
            Circle()
                .fill(Color.appPrimary)
                .frame(width: 32, height: 32)

            Image(systemName: "plus")
                .font(.system(size: 14, weight: .bold))
                .foregroundColor(Color.appTextOnPrimary)
        }
    }
}

// MARK: - Extensions

extension View {
    func cornerRadius(_ radius: CGFloat, corners: UIRectCorner) -> some View {
        clipShape(RoundedCorner(radius: radius, corners: corners))
    }
}

struct RoundedCorner: Shape {
    var radius: CGFloat = .infinity
    var corners: UIRectCorner = .allCorners

    func path(in rect: CGRect) -> Path {
        let path = UIBezierPath(
            roundedRect: rect,
            byRoundingCorners: corners,
            cornerRadii: CGSize(width: radius, height: radius)
        )
        return Path(path.cgPath)
    }
}

#Preview {
    NavigationStack {
        AllTasksView()
    }
}

