import type { CardColor, Hand } from '../types';
import CardView from './CardView';
import { emit } from '../lib/socket';

const COLOR_ORDER: CardColor[] = ['HEARTS', 'LEAVES', 'ACORNS', 'BELLS'];
const VALUE_ORDER = ['C7', 'C8', 'C9', 'C10', 'LOWER', 'UPPER', 'KING', 'ACE'];

function groupedByColor(hand: Hand): { color: CardColor; keys: string[] }[] {
  return COLOR_ORDER
    .map((color) => ({
      color,
      keys: Object.keys(hand)
        .filter((k) => hand[k].color === color)
        .sort((a, b) => VALUE_ORDER.indexOf(hand[a].value) - VALUE_ORDER.indexOf(hand[b].value)),
    }))
    .filter((g) => g.keys.length > 0);
}

interface Props {
  hand: Hand;
  myTurn: boolean;
  isPlayPhase: boolean;
  playableKeys?: Set<string>;
  desktop?: boolean;
}

export default function Hand({ hand, myTurn, isPlayPhase, playableKeys, desktop = false }: Props) {
  const groups = groupedByColor(hand);

  const canPlay = isPlayPhase && myTurn;

  const cardProps = (key: string) => {
    const legal = playableKeys === undefined || playableKeys.has(key);
    const playable = canPlay && legal;
    // Cards stay light by default; darken only the illegal ones, and only while
    // it's actually your turn to play.
    const dimmed = canPlay && !legal;
    return {
      card: hand[key],
      highlight: playable,
      disabled: dimmed,
      onClick: playable ? () => emit.playCard(key) : undefined,
    };
  };

  return (
    <div className="bg-header border-t border-[#111a13] px-4 pt-3 pb-7">
      <div className="flex items-center justify-center gap-2 mb-3">
        <div className="h-px flex-1 max-w-[80px] bg-gradient-to-r from-transparent to-gold/20" />
        <span className="uppercase tracking-[.13em] text-[9px] text-green-dim">Tvoje karty</span>
        <div className="h-px flex-1 max-w-[80px] bg-gradient-to-l from-transparent to-gold/20" />
      </div>

      {/* Fixed height reserves the card row even when the hand is briefly
          empty (last card of a round just played, next deal not in yet) --
          otherwise this whole area collapses and the layout jumps. */}
      <div className="flex items-end justify-center" style={{ minHeight: desktop ? 100 : 84 }}>
        {desktop ? (
          // Desktop has room — keep cards grouped by suit, wrap if needed.
          <div className="flex flex-wrap gap-3 justify-center items-end">
            {groups.map(({ color, keys }) => (
              <div key={color} className="flex gap-1 items-end">
                {keys.map((key) => (
                  <CardView key={key} size="xl" {...cardProps(key)} />
                ))}
              </div>
            ))}
          </div>
        ) : (
          <MobileHand groups={groups} cardProps={cardProps} />
        )}
      </div>
    </div>
  );
}

/** All cards in a single overlapping row that always fits the mobile width:
 *  small gap when few cards, partial overlap when many. */
function MobileHand({
  groups,
  cardProps,
}: {
  groups: { color: CardColor; keys: string[] }[];
  cardProps: (key: string) => { card: Hand[string]; highlight: boolean; disabled: boolean; onClick?: () => void };
}) {
  const keys = groups.flatMap((g) => g.keys);
  const n = keys.length;

  const CARD_W = 60; // matches CardView size "lg"
  const MAX_ROW = 300; // keep within a small phone's usable width (~360px screens)
  // Horizontal step between successive cards; <CARD_W means they overlap.
  const step = n > 1 ? Math.min(CARD_W + 6, (MAX_ROW - CARD_W) / (n - 1)) : 0;
  const margin = step - CARD_W; // negative → overlap, positive → gap

  return (
    <div className="flex justify-center items-end">
      {keys.map((key, i) => (
        <div
          key={key}
          className="relative"
          // Playable cards lift up — keep them above their neighbours.
          style={{ marginLeft: i === 0 ? 0 : margin, zIndex: cardProps(key).highlight ? 100 + i : i }}
        >
          <CardView size="lg" {...cardProps(key)} />
        </div>
      ))}
    </div>
  );
}
