import APIClient
import ComponentLibrary
import ComposableArchitecture
import FeatureShareAssetCreation
import FeatureToasts
import Foundation
import LyricsClient
import RequestState
import ShareAssetClient
import Sharing
import Utilities
import Waveform

@ObservableState
public struct ShareSheetState<Item: Shareable>: Equatable {
    typealias Platform = ShareableTarget.Platform

    var item: Item
    var itemAsClip: Clip? {
        return item as? Clip
    }

    var source: HooksFeedSource?

    let assetCreationPlayer = AssetCreationPlayerManager()
    var lyricsData: LyricsDataV2?
    var waveformData: WaveformData?
    var shareLinkAttribution: RequestState<ShareAttribution?> = .none

    var toast: ToastType?
    @Presents var destination: ShareSheetReducer<Item>.Destination.State?

    // Keeps track of platforms' last recently used sort order for presentation
    // Don't use this directly. Instead use `availableActions`.
    @Shared(.appStorage(.platformsLRUOrder)) var platformsLRUOrder: [Platform] = Platform.allCases

    var isCreator: Bool? = nil

    public init(item: Item, isCreator: Bool? = nil, source: HooksFeedSource? = nil) {
        self.item = item
        self.isCreator = isCreator
        self.source = source
    }
}

extension ShareSheetState {
    var effectiveShareURL: URL {
        shareLinkAttribution.value?.flatMap(\.url) ?? item.shareURL
    }

    var decoratedShareString: String {
        switch item.shareText {
        case .none:
            return effectiveShareURL.absoluteString

        case let .some(shareText):
            guard let shareText = shareText.ifNotEmpty else {
                return effectiveShareURL.absoluteString
            }
            return "\(effectiveShareURL.absoluteString)\n\(shareText)"
        }
    }

    var canUseVideoShareAssetPipeline: Bool {
        if let clip = itemAsClip, clip.duration > 0.0 {
            if clip.isInstrumental {
                return waveformData != nil
            } else {
                return waveformData != nil && lyricsData != nil
            }
        } else if item is Hook {
            // Hooks use hookDownloadClient instead of ShareAsset pipeline
            return true
        } else {
            /*
                Will need to account for more cases in the future
                if shareable applies to more types of items
             */
            return false
        }
    }
}
