import AnalyticsClient
import APIClient
import AVFoundation
import CommentsClient
import ComponentLibrary
import ComposableArchitecture
import FeatureClipDetail
import Foundation
import Localization
import MediaPlayer
import StatsigClient
import SwiftUI

public typealias OnAuthorTapped = (String) -> Void
public typealias OnRemixOfTapped = (ParentClip) -> Void
public typealias OnUserMentionTapped = (String) -> Void
public typealias UpgradeTapped = () -> Void

public struct ExpandedPlayerClipInfo: View {
    @Shared var playerState: OmniPlayerPlaybackState
    @Shared(.inMemory(.billingInfo)) var billingInfo: SubscriptionInfoResponse?
    @State var isCaptionExpanded: Bool = false
    let authorTapped: OnAuthorTapped
    let remixOfTapped: OnRemixOfTapped
    let userMentionTapped: OnUserMentionTapped?
    let upgradeTapped: UpgradeTapped
    let hideRemixOf: Bool
    let transitionCurve = Animation.easeInOut(duration: 0.3)

    public init(
        playerState: Shared<OmniPlayerPlaybackState>,
        authorTapped: @escaping OnAuthorTapped,
        remixOfTapped: @escaping OnRemixOfTapped,
        userMentionTapped: OnUserMentionTapped? = nil,
        upgradeTapped: @escaping UpgradeTapped,
        hideRemixOf: Bool
    ) {
        self._playerState = playerState
        self.authorTapped = authorTapped
        self.remixOfTapped = remixOfTapped
        self.userMentionTapped = userMentionTapped
        self.upgradeTapped = upgradeTapped
        self.hideRemixOf = hideRemixOf
    }

    private var clip: Clip {
        playerState.clip
    }

    public var body: some View {
        VStack(alignment: .leading, spacing: 8) {
            scrollingTitleBar
                .foregroundColor(.SemanticV1.textPrimary)
                .transition(.opacity)
                .padding(.top, 4.0)
                .multilineTextAlignment(.leading)
                .lineLimit(1)
            ExpandedPlayerAuthorCapsule(
                avatarImageUrl: clip.avatarImageUrl,
                displayName: clip.displayName,
                authorTapped: { authorTapped(clip.handle) }
            )
            ExpandedPlayerRemixOfInfo(
                clip: clip,
                remixOfTapped: { remixOfTapped($0) }
            )
            .opacity(hideRemixOf ? 0 : 1)
            .frame(height: hideRemixOf ? 0 : nil)
            .clipped()
            .allowsHitTesting(!hideRemixOf)
            .animation(transitionCurve, value: hideRemixOf)

            if clip.type == .preview, !clip.isUnlockingPreview(isPaidUser: billingInfo?.plan != nil) {
                ModelPreviewUpgradeButton(filled: true) {
                    upgradeTapped()
                }
            }

            if let caption = clip.caption?.ifNotEmpty {
                ExpandableText(
                    InteractiveTextFormatter.formatCaptionText(
                        caption,
                        mentions: clip.captionMentions,
                        config: .playerCaption
                    ),
                    font: .playerCaption,
                    condensedLineLimit: 2,
                    isExpanded: $isCaptionExpanded
                )
                .onUserMentionTapped { mention in
                    userMentionTapped?(mention)
                }
            }
        }
        .opacity(playerState.isScrubbing ? 0.2 : 1)
        .animation(.easeInOut(duration: 0.3), value: playerState.isScrubbing)
        .shadow(color: Color.SemanticV2.backgroundDarkOverlay, radius: 4)
    }

    @ViewBuilder
    private var scrollingTitleBar: some View {
        HStack {
            MarqueeText(
                text: clip.title,
                font: TypographyV1.headline4.uiFont ?? .systemFont(ofSize: 17),
                leftFade: 4,
                rightFade: 4,
                startDelay: 1,
                alignment: .leading
            )
            .id(clip.id)

            if clip.type == .preview {
                if clip.isUnlockingPreview(isPaidUser: billingInfo?.plan != nil) {
                    Pill(type: .modelPreview(version: .loading))
                        .fixedSize()
                } else {
                    Pill(type: .modelPreview(version: .init(from: clip.highLevelModel)))
                        .fixedSize()
                }
            }
        }
    }
}
