import SwiftUI

struct CardStackView: View {
    let cards: [Card]
    let location: CardLocation
    let layout: CardLayout
    let cardFaceStyle: CardFaceStyle
    let cardBackDesign: CardBackDesign
    @Bindable var viewModel: GameViewModel

    var body: some View {
        ZStack(alignment: .top) {
            // Empty slot placeholder — also a drop target
            CardView(card: nil, cardFaceStyle: cardFaceStyle, cardBackDesign: cardBackDesign,
                     size: layout.cardSize())
                .dropTarget(location)
                .accessibilityLabel(emptySlotLabel)

            // Stacked cards
            ForEach(Array(cards.enumerated()), id: \.element.id) { index, card in
                let isInDrag = viewModel.draggedCards.contains(card)
                let isLast = index == cards.count - 1

                CardView(card: card, cardFaceStyle: cardFaceStyle, cardBackDesign: cardBackDesign,
                         size: layout.cardSize(),
                         isHighlighted: isHinted(card))
                    .offset(y: yOffset(for: index))
                    .opacity(isInDrag ? 0.3 : 1.0)
                    .onTapGesture {
                        viewModel.tapCard(at: location, cardIndex: index)
                    }
                    .simultaneousGesture(
                        card.isFaceUp ? dragGesture(for: card, at: index) : nil
                    )
                    .overlay {
                        if isLast {
                            Color.clear
                                .dropTarget(location)
                                .offset(y: yOffset(for: index))
                        }
                    }
            }
        }
        .frame(width: layout.cardWidth)
        .accessibilityElement(children: .contain)
        .accessibilityLabel(stackAccessibilityLabel)
    }

    private var emptySlotLabel: Text {
        switch location {
        case .tableau(let i): Text("Empty tableau column \(i + 1)")
        case .foundation(let i): Text("Empty foundation \(i + 1)")
        case .freeCell(let i): Text("Empty free cell \(i + 1)")
        default: Text("Empty slot")
        }
    }

    private var stackAccessibilityLabel: Text {
        switch location {
        case .tableau(let i):
            let count = cards.count
            return Text("Tableau column \(i + 1), \(count) card\(count == 1 ? "" : "s")")
        default:
            return Text("")
        }
    }

    private func yOffset(for index: Int) -> CGFloat {
        var offset: CGFloat = 0
        for i in 0..<index {
            offset += cards[i].isFaceUp ? layout.verticalOverlapFaceUp : layout.verticalOverlapFaceDown
        }
        return offset
    }

    private func dragGesture(for card: Card, at index: Int) -> some Gesture {
        LongPressGesture(minimumDuration: 0.15)
            .sequenced(before: DragGesture(coordinateSpace: .named("board")))
            .onChanged { value in
                if case .second(true, let drag?) = value {
                    if viewModel.draggedCards.isEmpty {
                        let cardsToMove = Array(cards[index...])
                        viewModel.beginDrag(cards: cardsToMove, from: location)
                    }
                    viewModel.dragPosition = drag.location
                }
            }
            .onEnded { value in
                if case .second(true, let drag?) = value {
                    viewModel.endDrag(at: drag.location)
                } else {
                    viewModel.cancelDrag()
                }
            }
    }

    private func isHinted(_ card: Card) -> Bool {
        guard viewModel.isShowingHint, let hint = viewModel.currentHint else { return false }
        return hint.cards.contains(card)
    }
}
