import APIClient
import ComposableArchitecture
import EventBusClient
import FeatureClipDetail
import FeatureHookDownload
import FeatureToasts
import Foundation
import HookActionsClient
import Localization
import NavigationRouterClient
import os.log
import SongActionsClient
import TabBarUtilities
import Utilities
import StatsigClient

let log = Logger(category: "FeatureHooksMoreMenu")

@Reducer
public struct HookActions {
    @ObservableState
    public struct State: Equatable {
        let hook: Hook
        let source: HooksFeedSource?

        @Shared var me: Me

        var allowComments: Bool

        var isMe: Bool {
            hook.user != nil && hook.authorUserHandle == me.user.handle
        }

        var canRemix: Bool {
            isMe || (hook.clip?.canRemix ?? false)
        }

        var canDownloadHook: Bool {
            FeatureFlag.hooks.allowAllHookDownloads || (FeatureFlag.hooks.allowSelfHookDownload && isMe)
        }

        public init(hook: Hook, me: Shared<Me>, source: HooksFeedSource? = nil) {
            self.hook = hook
            self._me = me
            self.source = source

            self.allowComments = hook.allowComments
        }
    }

    @Dependency(\.dismiss) private var dismiss
    @Dependency(\.toastClient.show) private var showToast
    @Dependency(\.eventBus.getOmniplayerChannel) private var getOmniplayerChannel
    @Dependency(\.eventBus.sendClipEvent) private var sendClipEvent

    @Dependency(\.hookActionsClient) private var hookActionsClient
    @Dependency(\.hookDownloadClient) private var hookDownloadClient
    @Dependency(NavigationRouterClient.self) private var navigationRouter
    @Dependency(SongActionsClient.self) private var songActionsClient
    @Shared(.inMemory(.isOnHooksFeed)) var isOnHooksFeed: Bool = false

    public enum Action {
        case dismiss
        // First row actions
        case addToPlaylistTapped
        case likeSongTapped
        case shareHookTapped

        // Me actions
        case setCommentsAccess(Bool)
        case goToFullSongTapped
        case remixSongTapped
        case downloadHookTapped
        case deleteHookTapped

        // Other user actions
        case hideCreatorTapped
        case notInterestedTapped
        case reportInappropriateTapped

        case delegate(Delegate)

        public enum Delegate {
            case deleteHookTapped(Hook)
            case openOmniPlayerFromHooksFeed(Clip)
            case queueDestination(clip: Clip, destination: QueueDestinationType)
            case reportInappropriateTapped(Hook)
        }
    }

    public enum QueueDestinationType {
        case addToPlaylist
        case shareSheet
        case remixActions
    }

    public init() {}

    public var body: some ReducerOf<Self> {
        Reduce<State, Action> { state, action in
            struct ClipEventCancellableId: Hashable {}

            switch action {
            case .addToPlaylistTapped:
                guard let clip = state.hook.clip else {
                    let warningToast = ToastReducer.State.ToastType.warning(
                        L10n.FeatureHooks.actionNotComplete, position: .top
                    )
                    showToast(warningToast)
                    return .send(.dismiss)
                }
                return .send(.dismiss)
                    .concatenate(with: .send(.delegate(.queueDestination(clip: clip, destination: .addToPlaylist))))

            case .likeSongTapped:
                guard let clip = state.hook.clip else {
                    let warningToast = ToastReducer.State.ToastType.warning(
                        L10n.FeatureHooks.actionNotComplete, position: .top
                    )
                    showToast(warningToast)
                    return .send(.dismiss)
                }
                songActionsClient.setLiked(clip: clip, liked: !clip.isLiked, showToast: true, hook: nil, source: nil)
                return .send(.dismiss)

            case .shareHookTapped:
                // Use the existing share flow from HooksFeedReducer
                return .run { [hook = state.hook, source = state.source] _ in
                    @Dependency(\.eventBus.sendHookEvent) var sendHookEvent
                    sendHookEvent(.shareHook(hook, source: source))
                    await self.dismiss()
                }

            case .setCommentsAccess(let allow):
                state.allowComments = allow
                hookActionsClient.toggleComments(state.hook.id, allow)
                return .none

            case .goToFullSongTapped:
                if let clip = state.hook.clip {
                    if isOnHooksFeed {
                        // Dismiss the sheet then open OmniPlayer directly from Hooks Feed if we're there
                        return .send(.dismiss)
                            .concatenate(with: .send(.delegate(.openOmniPlayerFromHooksFeed(clip))))
                    } else {
                        getOmniplayerChannel().queue(.playClip(clip, queue: [clip], context: SessionContext(source: .hookActionsMenu(hookId: state.hook.id))))
                    }
                } else {
                    // If clip is not available, we could fetch it using originalClipId
                    // For now, just show a message
                    let warningToast = ToastReducer.State.ToastType.warning(
                        L10n.FeatureHooks.actionNotComplete, position: .top
                    )
                    showToast(warningToast)
                }
                return .send(.dismiss)

            case .remixSongTapped:
                guard let clip = state.hook.clip else {
                    let warningToast = ToastReducer.State.ToastType.warning(
                        L10n.FeatureHooks.actionNotComplete, position: .top
                    )
                    showToast(warningToast)
                    return .send(.dismiss)
                }
                return .send(.dismiss)
                    .concatenate(with: .send(.delegate(.queueDestination(clip: clip, destination: .remixActions))))

            case .downloadHookTapped:
                hookDownloadClient.triggerHookDownload(state.hook, .download, nil)

                return .send(.dismiss)

            case .deleteHookTapped:
                return .send(.delegate(.deleteHookTapped(state.hook)))

            case .hideCreatorTapped:
                return .run { [hook = state.hook, source = state.source] _ in
                    @Dependency(\.eventBus.sendHookEvent) var sendHookEvent
                    sendHookEvent(.showHideCreatorAlert(hook: hook, source: source))
                    // Don't dismiss - the brandedAlert will show on top of HookActionsMenu
                }

            case .notInterestedTapped:
                // Use HookActionsClient to dislike the hook
                hookActionsClient.toggleDislike(state.hook.id, state.hook.recommendationItemId)
                return .send(.dismiss)

            case .reportInappropriateTapped:
                return .send(.dismiss)
                    .concatenate(with: .send(.delegate(.reportInappropriateTapped(state.hook))))

            case .dismiss:
                return .run { _ in await self.dismiss() }

            case .delegate:
                return .none
            }
        }
        Analytics()
    }
}
