import APIClient
import ComponentLibrary
import ComposableArchitecture
import SwiftUI
import UIKit
import Utilities

// Backing view controller for HooksFeedView

// swiftlint:disable:next cyclomatic_complexity
public struct HooksFeedViewControllerWrapper: UIViewControllerRepresentable {
    let store: StoreOf<HooksFeedReducer>

    public init(store: StoreOf<HooksFeedReducer>) {
        self.store = store
    }

    public func makeUIViewController(context: Context) -> HooksFeedViewController {
        let viewController = HooksFeedViewController(feedId: store.feedId)

        viewController.onAction = { action in
            store.send(action)
        }

        viewController.updateMeHandle(store.meHandle)
        viewController.updateIsMuted(store.didTapToUnmute == false)

        context.coordinator.hooks = Array(store.hooks)
        context.coordinator.currentIndex = store.currentIndex
        context.coordinator.playingHookId = store.playingHookId
        context.coordinator.feedId = store.feedId
        context.coordinator.meHandle = store.meHandle
        context.coordinator.followStatus = store.hooksMetadata.followStatus
        context.coordinator.likeStatus = store.hooksMetadata.likeStatus
        context.coordinator.likeCount = store.hooksMetadata.likeCount
        context.coordinator.clipLikeStatus = store.hooksMetadata.clipLikeStatus
        context.coordinator.clipPlayCount = store.hooksMetadata.clipPlayCount
        context.coordinator.commentCount = store.hooksMetadata.commentCount
        context.coordinator.reportedStatus = store.hooksMetadata.reportedStatus
        context.coordinator.hiddenCreatorHandles = store.hooksMetadata.hiddenCreatorHandles
        context.coordinator.dislikeStatus = store.hooksMetadata.dislikeStatus
        context.coordinator.isFocused = store.isFocused
        context.coordinator.didTapToUnmute = store.didTapToUnmute

        viewController.updateFocusedStatus(store.isFocused)

        return viewController
    }

    // swiftlint:disable:next cyclomatic_complexity
    public func updateUIViewController(_ viewController: HooksFeedViewController, context: Context) {
        let coordinator = context.coordinator
        let newHooks = Array(store.hooks)
        let newCurrentIndex = store.currentIndex
        let newFeedId = store.feedId
        let newPlayingHookId = store.playingHookId
        let newMeHandle = store.meHandle
        let newFollowStatus = store.hooksMetadata.followStatus
        let newLikeStatus = store.hooksMetadata.likeStatus
        let newLikeCount = store.hooksMetadata.likeCount
        let newClipLikeStatus = store.hooksMetadata.clipLikeStatus
        let newClipPlayCount = store.hooksMetadata.clipPlayCount
        let newCommentCount = store.hooksMetadata.commentCount
        let newReportedStatus = store.hooksMetadata.reportedStatus
        let newHiddenCreatorHandles = store.hooksMetadata.hiddenCreatorHandles
        let newDislikeStatus = store.hooksMetadata.dislikeStatus
        let newIsFocused = store.isFocused
        let newLyrics = store.hooksMetadata.lyrics
        let refreshType = store.refreshType
        let newDidTapToUnmute = store.didTapToUnmute

        let shouldAnimate = store.shouldAnimateIndexChange
        if shouldAnimate, coordinator.currentIndex != newCurrentIndex {
            coordinator.currentIndex = newCurrentIndex
            viewController.animateToIndex(newCurrentIndex)
            store.send(.internal(.clearAnimationFlag))
            return
        }

        if refreshType == .reloadNext {
            // Update all coordinator state
            coordinator.hooks = newHooks
            coordinator.currentIndex = newCurrentIndex
            coordinator.playingHookId = newPlayingHookId
            coordinator.followStatus = newFollowStatus
            coordinator.likeStatus = newLikeStatus
            coordinator.likeCount = newLikeCount
            coordinator.clipLikeStatus = newClipLikeStatus
            coordinator.clipPlayCount = newClipPlayCount
            coordinator.commentCount = newCommentCount
            coordinator.reportedStatus = newReportedStatus
            coordinator.hiddenCreatorHandles = newHiddenCreatorHandles
            coordinator.dislikeStatus = newDislikeStatus
            coordinator.lyrics = newLyrics

            // We're not updating all hooks here, and don't want to modify
            // the current hook or previous ones, so we need to use replaceHooksAfterIndex
            viewController.replaceHooksAfterIndex(newCurrentIndex, with: newHooks)

            // Update all metadata in view controller
            viewController.updateFollowStatus(newFollowStatus)
            viewController.updateLikeStatus(newLikeStatus)
            viewController.updateLikeCount(newLikeCount)
            viewController.updateClipLikeStatus(newClipLikeStatus)
            viewController.updateClipPlayCount(newClipPlayCount)
            viewController.updateCommentCount(newCommentCount)
            viewController.updateReportedStatus(newReportedStatus)
            viewController.updateHiddenCreatorHandles(newHiddenCreatorHandles)
            viewController.updateDislikeStatus(newDislikeStatus)
            viewController.updateLyrics(newLyrics)

            store.send(.internal(.clearShouldRefreshFlag))
            return
        }

        // Check if we just need to reload one hook (the current one)
        if refreshType == .reloadCurrentIndex,
           abs(newHooks.count - coordinator.hooks.count) == 1,
           coordinator.hooks.isEmpty == false,
           newCurrentIndex == coordinator.currentIndex
        {
            let currentHook = newHooks[newCurrentIndex]
            let oldHook = coordinator.hooks[coordinator.currentIndex]
            guard currentHook != oldHook else { return }

            // Insert at current index
            coordinator.hooks.insert(currentHook, at: coordinator.currentIndex)
            coordinator.currentIndex = newCurrentIndex
            coordinator.playingHookId = newPlayingHookId
            coordinator.feedId = newFeedId
            coordinator.meHandle = newMeHandle
            coordinator.followStatus = newFollowStatus
            coordinator.likeStatus = newLikeStatus
            coordinator.likeCount = newLikeCount
            coordinator.clipLikeStatus = newClipLikeStatus
            coordinator.commentCount = newCommentCount
            coordinator.reportedStatus = newReportedStatus
            coordinator.hiddenCreatorHandles = newHiddenCreatorHandles
            coordinator.dislikeStatus = newDislikeStatus
            coordinator.isFocused = newIsFocused
            coordinator.didTapToUnmute = newDidTapToUnmute
            coordinator.lyrics = newLyrics
            viewController.insertHook(currentHook, at: coordinator.currentIndex)
            viewController.updateIsMuted(newDidTapToUnmute == false)
            viewController.updateFocusedStatus(newIsFocused)
            return
        }

        // Check if we need a full UI refresh after exiting detached mode or initial load
        if (refreshType == .restore && newFeedId == coordinator.feedId) ||
            (refreshType == .initialLoad && !newHooks.isEmpty) ||
            (refreshType != .none && newHooks != coordinator.hooks && !newHooks.isEmpty)
        {
            // Clear the flag immediately to prevent multiple refreshes
            store.send(.internal(.clearShouldRefreshFlag))

            // Update all coordinator state
            coordinator.hooks = newHooks
            coordinator.currentIndex = newCurrentIndex
            coordinator.playingHookId = newPlayingHookId
            coordinator.feedId = store.feedId
            coordinator.meHandle = newMeHandle
            coordinator.followStatus = newFollowStatus
            coordinator.likeStatus = newLikeStatus
            coordinator.likeCount = newLikeCount
            coordinator.clipLikeStatus = newClipLikeStatus
            coordinator.commentCount = newCommentCount
            coordinator.reportedStatus = newReportedStatus
            coordinator.hiddenCreatorHandles = newHiddenCreatorHandles
            coordinator.dislikeStatus = newDislikeStatus
            coordinator.isFocused = newIsFocused
            coordinator.didTapToUnmute = store.didTapToUnmute
            coordinator.lyrics = newLyrics

            if refreshType == .restore {
                // Sync SlidingWindowState from reducer state (source of truth)
                // This ensures we have the latest hooks with deletions applied
                viewController.updateHooks(newHooks, startIndex: newCurrentIndex, feedId: newFeedId, reload: false)
                viewController.reloadHooks()
                return
            }

            viewController.updateHooks(newHooks, startIndex: newCurrentIndex, feedId: newFeedId, reload: refreshType == .reloadFeed)
            viewController.updateFollowStatus(newFollowStatus)
            viewController.updateLikeStatus(newLikeStatus)
            viewController.updateLikeCount(newLikeCount)
            viewController.updateClipLikeStatus(newClipLikeStatus)
            viewController.updateCommentCount(newCommentCount)
            viewController.updateReportedStatus(newReportedStatus)
            viewController.updateHiddenCreatorHandles(newHiddenCreatorHandles)
            viewController.updateDislikeStatus(newDislikeStatus)
            viewController.updateIsMuted(store.didTapToUnmute == false)
            viewController.updateLyrics(newLyrics)
            return
        }

        if coordinator.hooks != newHooks {
            // Check if we're only appending
            let oldCount = coordinator.hooks.count
            let newCount = newHooks.count

            if newCount > oldCount,
               oldCount > 0,
               newHooks.prefix(oldCount).elementsEqual(coordinator.hooks, by: { $0.id == $1.id })
            {
                // We're adding hooks at the end
                let appendedHooks = Array(newHooks.suffix(newCount - oldCount))
                coordinator.hooks = newHooks
                viewController.appendHooks(appendedHooks)
            } else if newCount < oldCount,
                      oldCount > 0
            {
                // We're removing hooks - handle deletion
                coordinator.hooks = newHooks
                coordinator.currentIndex = newCurrentIndex
                coordinator.playingHookId = newPlayingHookId
                coordinator.feedId = newFeedId
                coordinator.meHandle = newMeHandle
                coordinator.followStatus = newFollowStatus
                coordinator.likeStatus = newLikeStatus
                coordinator.likeCount = newLikeCount
                coordinator.clipLikeStatus = newClipLikeStatus
                coordinator.clipPlayCount = newClipPlayCount
                coordinator.commentCount = newCommentCount
                coordinator.reportedStatus = newReportedStatus
                coordinator.hiddenCreatorHandles = newHiddenCreatorHandles
                coordinator.dislikeStatus = newDislikeStatus
                coordinator.isFocused = newIsFocused
                coordinator.didTapToUnmute = newDidTapToUnmute
                coordinator.lyrics = newLyrics

                // Update the view controller with the new hooks array
                viewController.updateHooks(newHooks, startIndex: newCurrentIndex, feedId: newFeedId, reload: false)

                // Update all metadata in view controller
                viewController.updateFollowStatus(newFollowStatus)
                viewController.updateLikeStatus(newLikeStatus)
                viewController.updateLikeCount(newLikeCount)
                viewController.updateClipLikeStatus(newClipLikeStatus)
                viewController.updateClipPlayCount(newClipPlayCount)
                viewController.updateCommentCount(newCommentCount)
                viewController.updateReportedStatus(newReportedStatus)
                viewController.updateHiddenCreatorHandles(newHiddenCreatorHandles)
                viewController.updateDislikeStatus(newDislikeStatus)
                viewController.updateIsMuted(newDidTapToUnmute == false)
                viewController.updateFocusedStatus(newIsFocused)
                viewController.updateLyrics(newLyrics)
            }
        }

        if coordinator.currentIndex != newCurrentIndex {
            coordinator.currentIndex = newCurrentIndex
            viewController.updateCurrentIndex(newCurrentIndex)
        }

        if coordinator.meHandle != newMeHandle {
            coordinator.meHandle = newMeHandle
            viewController.updateMeHandle(newMeHandle)
        }

        if coordinator.followStatus != newFollowStatus {
            coordinator.followStatus = newFollowStatus
            viewController.updateFollowStatus(newFollowStatus)
        }

        if coordinator.likeStatus != newLikeStatus {
            coordinator.likeStatus = newLikeStatus
            viewController.updateLikeStatus(newLikeStatus)
        }

        if coordinator.likeCount != newLikeCount {
            coordinator.likeCount = newLikeCount
            viewController.updateLikeCount(newLikeCount)
        }

        if coordinator.clipLikeStatus != newClipLikeStatus {
            coordinator.clipLikeStatus = newClipLikeStatus
            viewController.updateClipLikeStatus(newClipLikeStatus)
        }

        if coordinator.clipPlayCount != newClipPlayCount {
            coordinator.clipPlayCount = newClipPlayCount
            viewController.updateClipPlayCount(newClipPlayCount)
        }

        if coordinator.commentCount != newCommentCount {
            coordinator.commentCount = newCommentCount
            viewController.updateCommentCount(newCommentCount)
        }

        if coordinator.reportedStatus != newReportedStatus {
            coordinator.reportedStatus = newReportedStatus
            viewController.updateReportedStatus(newReportedStatus)
        }

        if coordinator.hiddenCreatorHandles != newHiddenCreatorHandles {
            coordinator.hiddenCreatorHandles = newHiddenCreatorHandles
            viewController.updateHiddenCreatorHandles(newHiddenCreatorHandles)
        }

        if coordinator.dislikeStatus != newDislikeStatus {
            coordinator.dislikeStatus = newDislikeStatus
            viewController.updateDislikeStatus(newDislikeStatus)
        }

        if coordinator.isFocused != newIsFocused {
            coordinator.isFocused = newIsFocused
            viewController.updateFocusedStatus(newIsFocused)
        }

        if coordinator.didTapToUnmute != store.didTapToUnmute {
            coordinator.didTapToUnmute = store.didTapToUnmute
            viewController.updateIsMuted(store.didTapToUnmute == false)
        }

        if coordinator.lyrics != newLyrics {
            coordinator.lyrics = newLyrics
            viewController.updateLyrics(newLyrics)
        }

        if coordinator.playingHookId != newPlayingHookId, newPlayingHookId != nil {
            coordinator.playingHookId = newPlayingHookId
            viewController.updatePlayingHookId(newPlayingHookId)
        }

        let newPlayerReadyIndex = store.playerReadyIndex
        if coordinator.playerReadyIndex != newPlayerReadyIndex, let readyIndex = newPlayerReadyIndex {
            coordinator.playerReadyIndex = newPlayerReadyIndex
            viewController.updateCellPlayer(for: readyIndex)
        }

        let newCurrentPlaybackState = store.currentPlaybackState
        if coordinator.currentPlaybackState != newCurrentPlaybackState {
            coordinator.currentPlaybackState = newCurrentPlaybackState
            viewController.updateCurrentPlaybackState(for: newCurrentIndex, playbackState: newCurrentPlaybackState)
        }

        // So the screen doesn't move around when swiping to show profile or when reloading
        let shouldDisableScroll = store.isSwipingToShowProfile || store.refreshType == .reloadFeed || !store.isFocused || store.disableScroll
        if coordinator.isScrollDisabled != shouldDisableScroll {
            coordinator.isScrollDisabled = shouldDisableScroll
            viewController.setScrollEnabled(!shouldDisableScroll)
        }
    }

    public func makeCoordinator() -> Coordinator {
        Coordinator(
            hooks: [],
            currentIndex: 0,
            playingHookId: nil,
            feedId: UUID(),
            meHandle: "",
            followStatus: [:],
            likeStatus: [:],
            likeCount: [:],
            clipLikeStatus: [:],
            commentCount: [:],
            reportedStatus: [:],
            hiddenCreatorHandles: [:],
            dislikeStatus: [:],
            isFocused: false,
            didTapToUnmute: false,
            lyrics: [:],
            playerReadyIndex: nil,
            currentPlaybackState: .loading
        )
    }

    public class Coordinator {
        var hooks: [Hook]
        var currentIndex: Int
        var playingHookId: String?
        var feedId: UUID
        var meHandle: String
        var followStatus: [String: Bool]
        var likeStatus: [String: Bool]
        var likeCount: [String: Int]
        var clipLikeStatus: [String: Bool]
        var clipPlayCount: [String: Int]
        var commentCount: [String: Int]
        var reportedStatus: [String: Bool]
        var hiddenCreatorHandles: [String: Bool]
        var dislikeStatus: [String: Bool]
        var didTapToUnmute: Bool
        var lyrics: [String: LyricsDataV2]
        var isScrollDisabled: Bool
        var isFocused: Bool
        var playerReadyIndex: Int?
        var currentPlaybackState: PlaybackState

        init(
            hooks: [Hook],
            currentIndex: Int,
            playingHookId: String?,
            feedId: UUID,
            meHandle: String,
            followStatus: [String: Bool],
            likeStatus: [String: Bool],
            likeCount: [String: Int],
            clipLikeStatus: [String: Bool],
            clipPlayCount: [String: Int] = [:],
            commentCount: [String: Int],
            reportedStatus: [String: Bool] = [:],
            hiddenCreatorHandles: [String: Bool] = [:],
            dislikeStatus: [String: Bool] = [:],
            isFocused: Bool = false,
            didTapToUnmute: Bool = false,

            lyrics: [String: LyricsDataV2],
            playerReadyIndex: Int? = nil,
            currentPlaybackState: PlaybackState = .loading
        ) {
            self.hooks = hooks
            self.currentIndex = currentIndex
            self.playingHookId = playingHookId
            self.feedId = feedId
            self.meHandle = meHandle
            self.followStatus = followStatus
            self.likeStatus = likeStatus
            self.likeCount = likeCount
            self.clipLikeStatus = clipLikeStatus
            self.clipPlayCount = clipPlayCount
            self.commentCount = commentCount
            self.reportedStatus = reportedStatus
            self.hiddenCreatorHandles = hiddenCreatorHandles
            self.dislikeStatus = dislikeStatus
            self.didTapToUnmute = didTapToUnmute
            self.lyrics = lyrics
            self.isScrollDisabled = false
            self.isFocused = isFocused
            self.playerReadyIndex = playerReadyIndex
            self.currentPlaybackState = currentPlaybackState
            self.playingHookId = playingHookId
        }
    }
}
