import ComposableArchitecture
import CoreMedia
import Foundation

struct SegmentPayload {
    var eventName: String
    var properties: Codable
}

enum SegmentPayloadError: LocalizedError {
    case unimplementedEvent(AnalyticsEvent)

    var errorDescription: String? {
        switch self {
        case let .unimplementedEvent(event): "Missing segment payload implementation for AnalyticsEvent: \(event.self)"
        }
    }
}

extension AnalyticsEvent {
    func getSegmentPayload(anonymousId: String, userId: String?) throws -> SegmentPayload {
        @Shared(.inMemory(.analyticsSessionId)) var sessionId: String?

        switch self {
        case let .onboardingAction(route):
            return SegmentPayload(
                eventName: self.eventName,
                properties: route.propertiesType.init(
                    actionName: route.actionName,
                    userId: userId,
                    anonymousId: anonymousId,
                    sessionId: sessionId
                )
            )

        case let .audioAction(route, clip, playbackMetadata):
            return SegmentPayload(
                eventName: self.eventName,
                properties: route.propertiesType.init(
                    actionName: route.actionName,
                    isMobile: true,
                    clipId: clip.id.remoteId,
                    isPublic: clip.isPublic,
                    isUserSongOwner: clip.userId == userId,
                    userId: userId,
                    isLiked: clip.isLiked,
                    isDisliked: clip.isDisliked,
                    anonymousId: anonymousId,
                    shareType: route.shareType,
                    isPlaying: playbackMetadata.isPlaying,
                    isStreaming: clip.status == .streaming,
                    elapsedTime: playbackMetadata.elapsedTime,
                    totalTime: playbackMetadata.totalTime,
                    fromCommandCenter: playbackMetadata.fromCommandCenter,
                    omniplayerIsExpanded: playbackMetadata.omniplayerIsExpanded,
                    sessionId: sessionId
                )
            )

        case let .general(route):
            return SegmentPayload(
                eventName: self.eventName,
                properties: route.propertiesType.init(
                    actionName: route.actionName,
                    userId: userId,
                    anonymousId: anonymousId,
                    description: route.description,
                    sessionId: sessionId
                )
            )

        default:
            throw SegmentPayloadError.unimplementedEvent(self)
        }
    }
}
