import SwiftUI

public struct ClipCard: View {
    let title: String
    let tags: String
    let imageUrl: String
    let playCount: Int
    let upvoteCount: Int
    let isLiked: Bool
    let commentCount: Int
    let avatarImageUrl: String?
    let displayName: String
    let userId: String?
    let clipId: String?
    let isLoading: Bool
    let didFailToLoad: Bool
    let cardTappedAction: () -> Void
    let authorTappedAction: () -> Void

    public init(
        title: String,
        tags: String,
        imageUrl: String,
        playCount: Int,
        upvoteCount: Int,
        isLiked: Bool,
        commentCount: Int,
        avatarImageUrl: String?,
        displayName: String,
        userId: String?,
        clipId: String?,
        isLoading: Bool,
        didFailToLoad: Bool = false,
        cardTappedAction: @escaping () -> Void,
        authorTappedAction: @escaping () -> Void
    ) {
        if isLoading {
            self.title = ""
            self.tags = ""
            self.imageUrl = ""
            self.playCount = 0
            self.upvoteCount = 0
            self.isLiked = false
            self.commentCount = 0
            self.avatarImageUrl = nil
            self.displayName = ""
            self.userId = nil
            self.clipId = nil
        } else {
            self.title = title
            self.tags = tags
            self.imageUrl = imageUrl
            self.playCount = playCount
            self.upvoteCount = upvoteCount
            self.isLiked = isLiked
            self.commentCount = commentCount
            self.avatarImageUrl = avatarImageUrl
            self.displayName = displayName
            self.userId = userId
            self.clipId = clipId
        }
        self.isLoading = isLoading
        self.didFailToLoad = didFailToLoad
        self.cardTappedAction = cardTappedAction
        self.authorTappedAction = authorTappedAction
    }

    private var annotationSizingScalar: CGFloat {
        return 3.6
    }

    private var annotationHeight: CGFloat {
        return 50.0
    }

    public var body: some View {
        VStack(alignment: .leading, spacing: 0) {
            clipInfoRowButton
            authorRowButton
        }
        .allowsHitTesting(!isLoading)
        .placeholderShimmering(isVisible: isShimmering)
    }

    private var clipInfoRowButton: some View {
        Button(action: cardTappedAction) {
            clipInfoRowLabel
        }
        .buttonStyle(ScaleButtonStyle(scaleAmount: 0.98))
    }

    private var clipInfoRowLabel: some View {
        VStack(spacing: 16) {
            clipImage
            clipTitleAndTags
        }
        .contentShape(.rect)
    }

    private var isShimmering: Bool {
        isLoading && !didFailToLoad
    }

    private var clipImage: some View {
        RemoteImage(url: imageUrl, fallbackId: clipId)
            .cornerRadius(8)
            .glassBorder(shape: .rect(cornerRadius: 8))
            .aspectRatio(3 / 4, contentMode: .fit)
            .overlay(alignment: .bottom) {
                HStack(spacing: 8.0) {
                    playCountLabel
                    upvoteCountLabel
                    commentCountLabel
                }
                .padding(8.0)
                .environment(\.colorScheme, .dark)
                .opacity(isLoading ? 0 : 1)
            }
            .frame(maxWidth: .infinity)
            .placeholder(isVisible: isLoading)
    }

    private var playCountLabel: some View {
        VStack(spacing: 4) {
            Image.Icon.playFilled
                .resizable()
                .frame(width: 16.0, height: 16.0)
                .foregroundColor(.SemanticV1.iconPrimary)
            Text(playCount.formatted(.number.notation(.compactName)))
                .typographyV1(.monospace.size { _ in 14.0 })
                .foregroundColor(.SemanticV1.textPrimary)
        }
        .frame(height: annotationHeight)
        .frame(maxWidth: .infinity)
        .glassBackground(shape: .rect(cornerRadius: 8), type: nil, fallbackStyle: .ultraThinMaterial)
    }

    private var upvoteCountLabel: some View {
        VStack(spacing: 4) {
            Image.Icon.thumbsUpFilled15V1
                .resizable()
                .frame(width: 16.0, height: 16.0)
                .foregroundColor(.SemanticV1.iconPrimary)
            Text(upvoteCount.formatted(.number.notation(.compactName)))
                .typographyV1(.monospace.size { _ in 14.0 })
                .foregroundColor(.SemanticV1.textPrimary)
        }
        .frame(height: annotationHeight)
        .frame(maxWidth: .infinity)
        .glassBackground(shape: .rect(cornerRadius: 8), type: nil, fallbackStyle: .ultraThinMaterial)
    }

    private var commentCountLabel: some View {
        VStack(spacing: 4) {
            Image.Icon.commentBubbleMore
                .resizable()
                .frame(width: 16.0, height: 16.0)
                .foregroundColor(.SemanticV1.iconPrimary)
            Text(commentCount.formatted(.number.notation(.compactName)))
                .typographyV1(.monospace.size { _ in 14.0 })
                .foregroundColor(.SemanticV1.textPrimary)
        }
        .frame(height: annotationHeight)
        .frame(maxWidth: .infinity)
        .glassBackground(shape: .rect(cornerRadius: 8), type: nil, fallbackStyle: .ultraThinMaterial)
    }

    private var clipTitleAndTags: some View {
        VStack(alignment: .leading, spacing: isLoading ? 10 : 0) {
            Text(title)
                .typographyV1(.body3)
                .foregroundColor(.SemanticV1.textPrimary)
                .lineLimit(1)
                .frame(maxWidth: .infinity, alignment: .leading)
                .placeholder(isVisible: isLoading)

            Text(tags.isEmpty ? " " : tags.capitalized)
                .typographyV1(.body2)
                .foregroundColor(.SemanticV1.textBrand)
                .lineLimit(1, reservesSpace: true)
                .fixedSize(horizontal: false, vertical: true)
                .frame(maxWidth: .infinity, alignment: .leading)
                .placeholder(isVisible: isLoading)
        }
    }

    private var authorRowButton: some View {
        Button(action: authorTappedAction) {
            authorRowLabel
        }
        .placeholder(isVisible: isLoading)
        .buttonStyle(ScaleButtonStyle(scaleAmount: 0.98))
        .padding(.top, 8)
    }

    private var authorRowLabel: some View {
        HStack(spacing: 4) {
            RemoteImage(url: avatarImageUrl, fallbackId: userId)
                .frame(width: 24, height: 24)
                .clipShape(Circle())
            Text(displayName)
                .typographyV1(.caption2)
                .foregroundColor(.SemanticV1.textPrimary)
                .lineLimit(1)
        }
    }
}

struct ClipCard_Previews: PreviewProvider {
    static var previews: some View {
        ClipCard(
            title: "Punk aint Dead",
            tags: "Punk, Rock, Metal, Pop Punk, Lively, Exagerated",
            imageUrl: "",
            playCount: 10000,
            upvoteCount: 1000,
            isLiked: true,
            commentCount: 1000,
            avatarImageUrl: nil,
            displayName: "AngelLove",
            userId: "1",
            clipId: "2",
            isLoading: false,
        ) {} authorTappedAction: {}
            .frame(width: 172, height: 325)

        ClipCard(
            title: "Punk aint Dead",
            tags: "Punk, Rock, Metal, Pop Punk, Lively, Exagerated",
            imageUrl: "",
            playCount: 10000,
            upvoteCount: 1000,
            isLiked: false,
            commentCount: 1000,
            avatarImageUrl: nil,
            displayName: "AngelLove",
            userId: "1",
            clipId: "2",
            isLoading: false,
        ) {} authorTappedAction: {}
            .frame(width: 172, height: 325)

        ClipCard(
            title: "Punk aint Dead",
            tags: "Punk, Rock, Metal, Pop Punk, Lively, Exagerated",
            imageUrl: "",
            playCount: 10000,
            upvoteCount: 1000,
            isLiked: false,
            commentCount: 1000,
            avatarImageUrl: nil,
            displayName: "AngelLove",
            userId: "1",
            clipId: "2",
            isLoading: true,
        ) {} authorTappedAction: {}
            .frame(width: 172, height: 325)
    }
}
