'use client'; import { useState } from 'react'; import type { Action, GameView } from '@/game/engine'; import { homeworldCard } from '@/game/homeworld-cards'; import { CardInspector, CardRules } from './card-inspector'; import { HomeworldFace } from './homeworld-cards'; import { Button } from './ui/button'; type Props = { game: GameView; act: (action: Action) => void; busy: boolean }; type Offer = NonNullable; export function HomeworldTupileCleanup({ game, act, busy }: Props) { const offer = game.homeworldTupileCleanup; if (!offer || offer.player !== game.me) return null; const authorized = game.decision?.kind === 'homeworldTupileCleanup' && game.decision.player === game.me && game.decision.event === offer.event; if (!authorized && !offer.blocked) return null; return ; } function CleanupChoice({ game, offer, act, busy }: Props & { offer: Offer }) { const [selection, setSelection] = useState([]); const me = game.players.find((player) => player.id === game.me); const eligibleIds = new Set(offer.eligibleCards); const cards = (me?.hand ?? []).filter((card) => eligibleIds.has(card.id)); const heldIds = new Set(cards.map((card) => card.id)); const selected = selection.filter((id) => heldIds.has(id)); const countsValid = Number.isSafeInteger(offer.limit) && offer.limit >= 0 && Number.isSafeInteger(offer.excess) && offer.excess > 0; const blocked = offer.blocked ?? (!countsValid ? 'The original hand-limit cleanup is unavailable.' : heldIds.size < offer.excess ? 'Not enough eligible held cards are available. Committed and reserved cards remain protected.' : null); const valid = !blocked && selected.length === offer.excess && new Set(selected).size === selected.length; const source = homeworldCard('tupile'); return (

{offer.playerName} · Tupile hand-limit cleanup

The occupied Tupile hand slot is no longer available. Discard exactly {offer.excess}{' '} {offer.excess === 1 ? 'card' : 'cards'} from your eligible held cards to return to the normal limit of {offer.limit}.

Only the server-offered original held cards can be selected. Committed and reserved cards are protected. This settles the lost slot; normal discard effects remain separate.

Development preview · {game.advanced ? <>Advanced retains the original occupation benefit until the occupier’s last own force leaves; contests, native high population and turn changes do not end it. : <>Basic provisionally ends the slot on departure, another foreign army or native high population. Regaining control does not cancel this earlier normal-limit discard.}{' '} Not complete or certified Homeworld rules.

Original occupation cleanup event: {offer.event}

{source && (
Inspect Tupile source card
)} Normal limit: {offer.limit} · Cards owed: {offer.excess} · Selected: {selected.length} {blocked && {blocked}}
{ event.preventDefault(); if (!busy && valid) act({ type: 'decision', event: offer.event, cards: selected }); }}>
Your eligible held cards {cards.map((card) => (
))} {!cards.length &&

No eligible held cards are available.

}
{!blocked && }
); }