import APIClient
import ComposableArchitecture
import Errors
import LinkPresentation
import Localization
import RequestState
import ShareAssetClient

/// Responsible for Share link URL attribution logic
@Reducer
public struct ShareLinkReducer<Item: Shareable> {
    public typealias State = ShareSheetState<Item>

    public enum Action {
        case loadAttribution
        case loadLinkPreview
        case setAttribution(Result<ShareAttribution?, AnyError>)
        case registerAttribution(ShareableTarget.Platform?)
    }

    public var body: some ReducerOf<Self> {
        Reduce { state, action in
            switch action {
            case .loadAttribution:
                guard !state.shareLinkAttribution.isLoading && !state.shareLinkAttribution.didSucceed else {
                    log.debug("Attempted to load link attribution while already loaded or in flight. Ignoring...")
                    return .none
                }

                state.shareLinkAttribution = .loading

                return .run { [item = state.item, source = state.source] send in
                    let result = await Result { try await item.getTemporaryAttributedShareURL(source: source) }
                        .mapError(AnyError.init)

                    await send(.setAttribution(result))
                    await send(.loadLinkPreview)
                }

            case .loadLinkPreview:
                return .run { [shareURL = state.effectiveShareURL] _ in
                    let metadataProvider = LPMetadataProvider()
                    let result = await Result { try? await metadataProvider.startFetchingMetadata(for: shareURL) }
                    // We don't do anything with the result but the fetch operation adds it to iOS's link preview cache.

                    switch result {
                    case .success:
                        log.debug("Successfully prefetched link preview so it's cached for iMessage share sheet.")
                    case let .failure(error):
                        log.telemetry.error(error, message: "Failed to prefetch link preview for iMessage share sheet.")
                    }
                }

            case let .setAttribution(result):
                state.shareLinkAttribution = .done(result)
                switch result {
                case .success:
                    // Auto-copy the short link immediately
                    UIPasteboard.general.string = state.effectiveShareURL.absoluteString
                    state.toast = .success(L10n.FeatureShareAssets.toastLinkCopied)

                case .failure(let error):
                    log.telemetry.error(error.underlying, message: "Error retrieving share link attribution.")
                }
                return .none

            case let .registerAttribution(platform):
                return .run { [item = state.item] _ in
                    let result = await Result { try await item.registerAttributedShareURL(for: platform) }
                        .mapError(AnyError.init)

                    let platformName = platform?.rawValue.lowercased() ?? "null"

                    switch result {
                    case .success:
                        log.debug("Successfully registered share link attribution for \"\(platformName)\".")
                    case let .failure(error):
                        log.telemetry.error(error.underlying, message: "Error registering share link attribution for \"\(platformName)\".")
                    }
                }
            }
        }
    }
}
