import AnalyticsClient
import APIClient
import ComposableArchitecture
import Foundation
import Utilities

extension HooksSongPicker {
    struct Analytics: AnalyticsReducer {
        var source: String = "hooks_song_picker"

        // swiftlint:disable:next cyclomatic_complexity
        func analytics(before: State, after: State, action: Action) -> Effect<Action> {
            switch action {
            case .recentsSongsTapped:
                track(
                    Event(
                        category: .hooksCreate,
                        actionName: .recentSongsTabTapped,
                        actionType: .tap,
                        elementType: .tab,
                        elementId: after.selectedTab.title,
                        context: createContext(tab: after.selectedTab.title)
                    )
                )
            case .publicSongsTapped:
                track(
                    Event(
                        category: .hooksCreate,
                        actionName: .publicSongsTabTapped,
                        actionType: .tap,
                        elementType: .tab,
                        elementId: after.selectedTab.title,
                        context: createContext(tab: after.selectedTab.title)
                    )
                )
            case .likedSongsTapped:
                track(
                    Event(
                        category: .hooksCreate,
                        actionName: .likedSongsTabTapped,
                        actionType: .tap,
                        elementType: .tab,
                        elementId: after.selectedTab.title,
                        context: createContext(tab: after.selectedTab.title)
                    )
                )
            case .snippetTapped(let snippet):
                track(
                    Event(
                        category: .hooksCreate,
                        actionName: .songTapped,
                        actionType: .tap,
                        elementType: .snippet,
                        elementId: snippet.clip.id.remoteId,
                        context: createContext(clipId: snippet.clip.id.remoteId, tab: before.selectedTab.title, isPaused: false)
                    )
                )
            case .createNewSongTapped:
                track(
                    Event(
                        category: .hooksCreate,
                        actionName: .createNewSongTapped,
                        actionType: .tap,
                        elementType: .button,
                        elementId: nil,
                        context: createContext(tab: before.selectedTab.title)
                    )
                )
            case .closeTapped:
                track(
                    Event(
                        category: .hooksCreate,
                        actionName: .closeTapped,
                        actionType: .tap,
                        elementType: .button,
                        elementId: nil,
                        context: createContext(tab: before.selectedTab.title)
                    )
                )
            case .setSelectedMovie(let movie):
                track(
                    Event(
                        category: .hooksCreate,
                        actionName: .videoSelected,
                        actionType: .tap,
                        elementType: .video,
                        elementId: movie?.url.absoluteString,
                        context: createContext(
                            clipId: before.selectedSongForOverlay?.clip.id.remoteId,
                            tab: before.selectedTab.title,
                            isPaused: before.isPlayingCurrentClip
                        )
                    )
                )
            case .snippetPlayer(let snippetPlayerEvent):
                switch snippetPlayerEvent {
                case .playPauseTapped(let snippet):
                    track(
                        Event(
                            category: .hooksCreate,
                            actionName: .songPlayPauseTapped,
                            actionType: .tap,
                            elementType: .button,
                            elementId: snippet.clip.id.remoteId,
                            context: createContext(clipId: snippet.clip.id.remoteId, tab: before.selectedTab.title, isPaused: before.isPlayingCurrentClip)
                        )
                    )
                case .proceedTapped(let snippet):
                    track(
                        Event(
                            category: .hooksCreate,
                            actionName: .songSelectionProceedTapped,
                            actionType: .tap,
                            elementType: .button,
                            elementId: snippet.clip.id.remoteId,
                            context: createContext(clipId: snippet.clip.id.remoteId, tab: before.selectedTab.title, isPaused: before.isPlayingCurrentClip)
                        )
                    )
                default:
                    break
                }

            default:
                    break
            }
            return .none
        }

        private func createContext(clipId: String? = nil, tab: String? = nil, isPaused: Bool? = nil) -> String {
            return HooksSongPickerAnalyticsContext(clipId: clipId, tab: tab, isPaused: isPaused).toJsonString()
        }
    }
}

private struct HooksSongPickerAnalyticsContext: Codable {
    public var clipId: String?
    public var tab: String?
    public var isPaused: Bool?

    public init(
        clipId: String?,
        tab: String?,
        isPaused: Bool?
    ) {
        self.clipId = clipId
        self.tab = tab
        self.isPaused = isPaused
    }

    public func toJsonString() -> String {
        guard let data = try? JSONEncoder().encode(self),
              let jsonString = String(data: data, encoding: .utf8)
        else {
            return "{}"
        }
        return jsonString
    }
}
