import Localization
import SwiftUI

// Card containing a title, body text, & clip metadata, copy button which copies body text to clipboard
public struct ClipDetailsExpandedCardView: View {
    let cardTitle: String
    let subtitleText: String?
    let bodyText: String?
    let negativeTags: String?
    let weirdnessConstraint: Double?
    let styleWeight: Double?
    let textColor: Color
    let backgroundColor: Color
    let buttonText: String?
    let buttonColor: Color?
    let shouldShowButton: Bool
    let onCopy: () -> Void
    let onButtonTap: () -> Void?

    @State var isShowingExpandedBodyText: Bool = false
    @State private var containerWidth: CGFloat = 0
    @State private var shouldShowGradient: Bool = false
    private var minimumCharCountForExpandedText: Int = 600

    public init(
        cardTitle: String,
        subtitleText: String?,
        bodyText: String?,
        negativeTags: String?,
        weirdnessConstraint: Double?,
        styleWeight: Double?,
        textColor: Color,
        backgroundColor: Color,
        buttonText: String?,
        buttonColor: Color? = Color.SemanticV2.backgroundFogThin,
        shouldShowButton: Bool,
        onCopy: @escaping () -> Void,
        onButtonTap: @escaping () -> Void?
    ) {
        self.cardTitle = cardTitle
        self.subtitleText = subtitleText
        self.bodyText = bodyText
        self.negativeTags = negativeTags
        self.weirdnessConstraint = weirdnessConstraint
        self.styleWeight = styleWeight
        self.textColor = textColor
        self.backgroundColor = backgroundColor
        self.buttonText = buttonText
        self.buttonColor = buttonColor
        self.shouldShowButton = shouldShowButton
        self.onCopy = onCopy
        self.onButtonTap = onButtonTap
    }

    public var body: some View {
        VStack(alignment: .leading, spacing: 16) {
            VStack(alignment: .leading, spacing: 8) {
                HStack {
                    Text(cardTitle)
                        .typographyV1(.playerCardBody.ppNeueMontrealBold())
                        .foregroundColor(textColor)
                    Spacer()

                    if let bodyText, !bodyText.isEmpty {
                        Button {
                            UIPasteboard.general.string = bodyText
                            onCopy()
                        } label: {
                            Image.Icon.copy
                                .foregroundColor(.SemanticV2.foregroundTertiaryGlass)
                                .frame(width: 18, height: 18)
                        }
                        .buttonStyle(ScaleButtonStyle(scaleAmount: 0.9))
                    }
                }

                if let subtitleText, !subtitleText.isEmpty, (bodyText?.count ?? 0) >= 100, isShowingExpandedBodyText {
                    Text(subtitleText)
                        .typographyV1(.playerCardBodyItalic)
                        .foregroundColor(textColor)
                }
            }

            if let bodyText, !bodyText.isEmpty {
                expandableBodyText
            }

            if let negativeTags, !negativeTags.isEmpty, isShowingExpandedBodyText {
                Text(formatNegativeTags(negativeTags))
                    .typographyV1(.playerCardBody.neueMontrealRegular())
                    .foregroundColor(textColor)
                    .lineLimit(1)
            }

            if weirdnessConstraint != nil || styleWeight != nil, isShowingExpandedBodyText {
                sliderMetadata
            }

            if let buttonText, shouldShowButton {
                Button(action: {
                    onButtonTap()
                }) {
                    Text(buttonText)
                        .typographyV1(.caption.neueMontrealRegular().kerning(0.28))
                        .foregroundStyle(Color.SemanticV2.foregroundPrimary)
                        .padding(.vertical, 14)
                        .frame(maxWidth: .infinity)
                }
                .background(buttonColor)
                .cornerRadius(50.0)
            }
        }
        .padding(16)
        .glassBackground(shape: .rect(cornerRadius: 16), fallbackStyle: backgroundColor)
        .onAppear {
            if let bodyText = bodyText, bodyText.count > minimumCharCountForExpandedText {
                isShowingExpandedBodyText = false
            } else {
                isShowingExpandedBodyText = true
            }
        }
        .onTapGesture {
            handleCardTapped()
        }
        .readSize { size in
            let width = size.width - 32 // Account for padding
            if containerWidth != width {
                containerWidth = width
                updateOverflowGradientOverlay(width: width)
            }
        }
    }

    @ViewBuilder
    private var expandableBodyText: some View {
        if let bodyText {
            ZStack(alignment: .topLeading) {
                // Truncated text (always rendered)
                Text(bodyText)
                    .typographyV1(.playerCardBody.neueMontrealRegular())
                    .lineLimit(12)
                    .truncationMode(.tail)
                    .frame(maxWidth: .infinity, alignment: .leading)
                    .opacity(isShowingExpandedBodyText ? 0 : 1)

                // Full text (always rendered)
                Text(bodyText)
                    .typographyV1(.playerCardBody.neueMontrealRegular())
                    .frame(maxWidth: .infinity, alignment: .leading)
                    .opacity(isShowingExpandedBodyText ? 1 : 0)
            }
            .clipped()
            .mask(textMask)
        }
    }

    @ViewBuilder
    private var textMask: some View {
        if !isShowingExpandedBodyText && shouldShowGradient {
            VStack(spacing: 0) {
                Rectangle()
                    .fill(Color.white)

                LinearGradient(
                    gradient: Gradient(stops: [
                        .init(color: Color.white, location: 0),
                        .init(color: Color.clear, location: 1),
                    ]),
                    startPoint: .top,
                    endPoint: .bottom
                )
                .frame(height: 11)
            }
        } else {
            Rectangle()
                .fill(Color.white)
        }
    }

    private func updateOverflowGradientOverlay(width: CGFloat) {
        guard let bodyText, !bodyText.isEmpty, width > 0 else {
            shouldShowGradient = false
            return
        }

        let typography = TypographyV1.playerCardBody.neueMontrealRegular()
        guard let uiFont = typography.uiFont else {
            shouldShowGradient = false // Fallback to not showing gradient if we can't get the font
            return
        }

        // Check if the text would take more than 6 lines
        let fitsInSixLines = bodyText.fitsIn(lineCount: 6, font: uiFont, containerWidth: width)

        // Show gradient if text is long OR if there are metadata values that would be shown when expanded
        let hasMetadata = weirdnessConstraint != nil || styleWeight != nil || negativeTags != nil
        shouldShowGradient = !fitsInSixLines || hasMetadata
    }

    @ViewBuilder
    private var sliderMetadata: some View {
        VStack(spacing: 8) {
            if let weirdnessConstraint {
                metadataRow(
                    label: L10n.FeatureClipDetail.weirdness,
                    value: weirdnessConstraint.formatted(.percent.precision(.fractionLength(0)))
                )
            }

            if let styleWeight {
                metadataRow(
                    label: L10n.FeatureClipDetail.styleInfluence,
                    value: styleWeight.formatted(.percent.precision(.fractionLength(0)))
                )
            }
        }
    }

    @ViewBuilder
    func metadataRow(label: String, value: String) -> some View {
        HStack {
            Text(label)
                .typographyV1(.playerCardBody.neueMontrealMedium())
                .foregroundStyle(textColor)
            Spacer()
            Text(value)
                .typographyV1(.playerCardBody.neueMontrealMedium())
                .foregroundStyle(Color.SemanticV2.foregroundTertiaryGlass)
        }
    }

    func formatNegativeTags(_ tags: String) -> String {
        // Split by comma, preserving segments
        let parts = tags.split(separator: ",", omittingEmptySubsequences: false)

        let formattedParts = parts.map { part in
            let trimmed = part.trimmingCharacters(in: .whitespaces)
            guard let firstSpace = trimmed.firstIndex(of: " ") else {
                // Only one word in this part
                return "-" + trimmed
            }

            // Multiple words: prefix only the first
            let firstWord = trimmed[..<firstSpace]
            let rest = trimmed[firstSpace...]
            return "-" + firstWord + rest
        }

        // Join parts back with commas and a space
        return formattedParts.joined(separator: ", ")
    }

    private func handleCardTapped() {
        if let bodyText, !bodyText.isEmpty {
            self.isShowingExpandedBodyText.toggle()
        }
    }
}

#Preview {
    VStack {
        ClipDetailsExpandedCardView(
            cardTitle: "this is the card title",
            subtitleText: "Pop, Funk, Jazz",
            bodyText: "this is the body text!",
            negativeTags: "pop, rock",
            weirdnessConstraint: 0.94834,
            styleWeight: 0.4538,
            textColor: Color.SemanticV1.textPrimary,
            backgroundColor: Color.SemanticV1.backgroundSecondary,
            buttonText: "Reuse Styles",
            buttonColor: Color.SemanticV2.foregroundPrimary,
            shouldShowButton: true,
            onCopy: {},
            onButtonTap: {}
        )

        ClipDetailsExpandedCardView(
            cardTitle: "this is the card title",
            subtitleText: "Pop, Funk, Jazz",
            bodyText: nil,
            negativeTags: "pop, rock, longer, longer, longer, longer, longer",
            weirdnessConstraint: 0.94834,
            styleWeight: 0.4538,
            textColor: Color.SemanticV2.foregroundPrimary,
            backgroundColor: Color.SemanticV2.backgroundFogThin,
            buttonText: "Reuse Styles",
            buttonColor: Color.SemanticV2.foregroundPrimary,
            shouldShowButton: false,
            onCopy: {},
            onButtonTap: {}
        )

        ClipDetailsExpandedCardView(
            cardTitle: "Card without copy",
            subtitleText: nil,
            bodyText: "Some content here",
            negativeTags: nil,
            weirdnessConstraint: nil,
            styleWeight: nil,
            textColor: Color.SemanticV1.textPrimary,
            backgroundColor: Color.SemanticV1.backgroundSecondary,
            buttonText: "Reuse Styles",
            buttonColor: Color.SemanticV2.foregroundPrimary,
            shouldShowButton: true,
            onCopy: {},
            onButtonTap: {}
        )
    }
}
