import APIClient
import ComponentLibrary
import ComposableArchitecture
import EventBusClient
import FeatureToasts
import Localization
import StatsigClient
import SwiftUI

@Reducer
public struct MoreInfo {
    @ObservableState
    public struct State: Equatable {
        var shouldShowMore: Bool = false
        let clip: Clip
        var toast: ToastType?
        @Shared var me: Me

        var isMe: Bool {
            clip.userId == me.user.id
        }

        public var canRemix: Bool {
            (isMe || clip.canRemix)
            && !clip.isScene
                && FeatureFlag.create.remixAndAttribution
        }

        public init(clip: Clip, me: Shared<Me>) {
            self.clip = clip
            self._me = me
        }
    }

    public enum Action: Equatable, BindableAction {
        case binding(BindingAction<State>)
        case setToast(ToastType?)
        case didTapCopyButton(ClipboardCopyType)
        case dismiss
        case `internal`(Internal)
        case reuseClipMetadata(ClipReuseType)

        public enum Internal: Equatable {
            case successfulCopyToast(ClipboardCopyType)
        }
    }

    public init() {}

    @Dependency(\.dismiss) var dismiss
    @Dependency(\.toastClient.show) var showToast
    @Dependency(\.eventBus.getCreateChannel) var getCreateChannel

    public var body: some ReducerOf<Self> {
        BindingReducer()

        Reduce<State, Action> { state, action in
            switch action {
            case let .setToast(toast):
                state.toast = toast
                return .none

            case .dismiss:
                return .run { _ in await self.dismiss() }

            case .didTapCopyButton(let copyType):
                return .send(.internal(.successfulCopyToast(copyType)))

            case .internal(.successfulCopyToast(let copyType)):
                let message: String
                switch copyType {
                case .lyrics:
                    message = L10n.FeatureClipDetail.lyricsCopySuccessMessage
                case .displayTags:
                    message = L10n.FeatureClipDetail.stylesCopySuccessMessage
                case .songTags:
                    message = L10n.FeatureClipDetail.stylesCopySuccessMessage
                }

                let successToast = ToastReducer.State.ToastType.success(
                    message, position: .bottom
                )

                return .send(.setToast(successToast))

            case .reuseClipMetadata(let reuseType):
                let prompt = Prompt(
                    title: state.clip.title,
                    lyrics: reuseType == .lyrics ? state.clip.prompt : "",
                    styles: reuseType == .styles ? state.clip.tags : "",
                    excludeStyles: reuseType == .styles ? (state.clip.negativeTags ?? "") : "",
                    styleWeight: reuseType == .styles ? state.clip.styleWeight : nil,
                    weirdnessConstraint: reuseType == .styles ? state.clip.weirdnessConstraint : nil
                )
                return .run { _ in
                    await dismiss()
                    getCreateChannel().queue(.reusePrompt(prompt: prompt))
                }

            case .binding, .internal:
                return .none
            }
        }
    }
}

public struct MoreInfoView: View {
    @Bindable var store: StoreOf<MoreInfo>

    var formattedCreationDate: String {
        return (store.clip.createdAt ?? Date()).formatted(
            .dateTime
                .month(.wide)
                .day(.defaultDigits)
                .year()
                .hour(.defaultDigits(amPM: .wide))
                .minute()
        )
    }

    private var shouldShowStylesCard: Bool {
        !store.clip.tags.isEmpty || !(store.clip.negativeTags?.isEmpty ?? true)
    }

    private var shouldShowLyricsCard: Bool {
        !store.clip.prompt.isEmpty
    }

    public init(store: StoreOf<MoreInfo>) {
        self.store = store
    }

    public var body: some View {
        ScrollView {
            VStack(alignment: .leading, spacing: 20) {
                if shouldShowStylesCard {
                    stylesCard
                }

                if shouldShowLyricsCard {
                    lyricsCard
                }

                createdAt
            }
        }
        .scrollIndicators(.never)
        .padding(.horizontal, 16)
        .sheetNavigationBar(
            leading: { EmptyView() },
            center: { header },
            trailing: {
                ToolbarButton(
                    .close,
                    color: Color.SemanticV1.iconPrimary,
                    background: Color.SemanticV1.backgroundSecondary
                ) {
                    store.send(.dismiss)
                }
                .frame(height: 44)
            }
        )
        .toast($store.toast, position: .bottom, colorScheme: .dark)
        .presentationCornerRadius(40, conditional: true)
        .presentationBackground(Color.SemanticV1.backgroundPrimary)
        .presentationDragIndicator(.visible)
    }

    @ViewBuilder
    var header: some View {
        VStack(alignment: .center, spacing: 4) {
            scrollingTitleBar
                .lineLimit(1)
                .foregroundStyle(Color.SemanticV1.textPrimary)
                .frame(height: 19)
            Text(L10n.FeatureClipDetail.by(store.state.clip.displayName))
                .typographyV1(TypographyV1.moreInfoCaption)
                .foregroundStyle(Color.SemanticV1.foregroundInactive)
        }
    }

    private var scrollingTitleBar: some View {
        MarqueeText(
            text: store.clip.title,
            font: TypographyV1.heading4.uiFont ?? .systemFont(ofSize: 15),
            leftFade: 4,
            rightFade: 44,
            startDelay: 3,
            alignment: .center
        )
    }

    @ViewBuilder
    private var stylesCard: some View {
        ClipDetailsExpandedCardView(
            cardTitle: L10n.FeatureClipDetail.styleSectionTitle,
            subtitleText: store.clip.displayTags?.capitalized,
            bodyText: store.clip.tags.capitalized,
            negativeTags: store.clip.negativeTags,
            weirdnessConstraint: store.clip.weirdnessConstraint,
            styleWeight: store.clip.styleWeight,
            textColor: Color.SemanticV1.textPrimary,
            backgroundColor: Color.SemanticV1.backgroundSecondary,
            buttonText: L10n.FeatureClipDetail.reuseStyle,
            buttonColor: Color.SemanticV2.backgroundGlassThin,
            shouldShowButton: store.canRemix,
            onCopy: { store.send(.setToast(.success(L10n.FeatureOmniPlayer.stylesCopySuccessMessage))) },
            onButtonTap: {
                store.send(.reuseClipMetadata(.styles))
            }
        )
    }

    @ViewBuilder
    private var lyricsCard: some View {
        ClipDetailsSimpleCardView(
            cardTitle: L10n.FeatureClipDetail.lyricsSectionTitle,
            bodyText: store.clip.prompt,
            textColor: Color.SemanticV1.textPrimary,
            backgroundColor: Color.SemanticV1.backgroundSecondary,
            buttonText: L10n.FeatureClipDetail.reuseLyrics,
            buttonColor: Color.SemanticV2.backgroundGlassThin,
            shouldShowButton: store.canRemix,
            onCopy: { store.send(.didTapCopyButton(.lyrics)) },
            onButtonTap: {
                store.send(.reuseClipMetadata(.lyrics))
            }
        )
    }

    @ViewBuilder
    private func styleDescriptionCard(title: String, body: String?, copyType: ClipboardCopyType) -> some View {
        VStack(alignment: .leading, spacing: 8) {
            HStack {
                Text(title)
                    .foregroundColor(Color.SemanticV1.textPrimary)
                    .typographyV1(.playerCardBody.ppNeueMontrealSemiBold())
                Spacer()
                Button(action: {
                    switch copyType {
                    case .lyrics:
                        if let lyrics = body, !lyrics.isEmpty {
                            UIPasteboard.general.string = lyrics
                            store.send(.didTapCopyButton(.lyrics))
                        } else {
                            UIPasteboard.general.string = L10n.FeatureClipDetail.emptyLyricsSectionTitle
                        }

                    case .songTags:
                        if let songTags = body, !songTags.isEmpty {
                            UIPasteboard.general.string = songTags
                            store.send(.didTapCopyButton(.songTags))
                        } else {
                            UIPasteboard.general.string = L10n.FeatureClipDetail.emptySongTagsTitle
                        }

                    case .displayTags:
                        if let displayTags = body, !displayTags.isEmpty {
                            UIPasteboard.general.string = displayTags
                            store.send(.didTapCopyButton(.displayTags))
                        } else {
                            UIPasteboard.general.string = L10n.FeatureClipDetail.emptyStyleTagsTitle
                        }
                    }
                }) {
                    Image.Icon.copy
                        .renderingMode(.template)
                        .resizable()
                        .frame(width: 18, height: 18)
                }
                .buttonStyle(ScaleButtonStyle(scaleAmount: 0.9))
            }

            if let body = body {
                Text(body)
                    .typographyV1(.playerCardBody.neueMontrealRegular())
                    .foregroundColor(Color.SemanticV1.textPrimary)
                    .opacity(0.6)
                    .fixedSize(horizontal: false, vertical: true)
                    .multilineTextAlignment(.leading)
            }
        }
        .padding([.horizontal, .vertical], 12)
        .glassBackground(shape: .rect(cornerRadius: 10), fallbackStyle: Color.SemanticV1.backgroundSecondary)
    }

    @ViewBuilder
    var createdAt: some View {
        HStack {
            Text("\(L10n.FeatureClipDetail.created): \(formattedCreationDate)")
                .typographyV1(.playerCardBody.neueMontrealRegular())
                .foregroundStyle(Color.SemanticV1.textTertiary)
            versioningPill
        }
        .padding(.vertical, 15)
        .padding(.leading, 12)
        .padding(.trailing, 10)
        .frame(maxWidth: .infinity)
        .glassBackground(shape: .rect(cornerRadius: 10), fallbackStyle: Color.SemanticV1.backgroundSecondary)
    }

    @ViewBuilder
    private var versioningPill: some View {
        // Use ModelBadgeStyle if feature flag is enabled and style is available
        if FeatureFlag.legacy.v5LaunchModelStyles,
           let modelBadgeStyle = store.clip.modelBadgeStyle
        {
            Pill(type: .modelBadge(style: modelBadgeStyle))
        } else {
            // Fallback to default versioning pills
            switch store.clip.highLevelModel {
            case .previousToV4:
                EmptyView()

            case .v5:
                Pill(type: .versioning(version: .v5))

            case .v4:
                Pill(type: .versioning(version: .v4))

            case .v4_5:
                Pill(type: .versioning(version: .v4_5))

            case .v4_5Plus:
                Pill(type: .versioning(version: .v4_5Plus))
            }
        }
    }
}

public enum ClipboardCopyType: Equatable {
    case lyrics
    case songTags
    case displayTags
}

public enum ClipReuseType {
    case lyrics
    case styles
}
