<script lang="ts">
  import type { ChatMessage } from '../lib/model';
  import { t } from '../lib/i18n/index.svelte';
  import { connection } from '../lib/connection.svelte';

  let {
    messages,
    myId,
    busy,
    myTurn = false,
    canSend = false,
    canNudge = false,
    waiting = false,
    nudgeOnCooldown = false,
    vsAi = false,
    blocked = false,
    onsend,
    onnudge,
  }: {
    messages: ChatMessage[];
    myId: string;
    busy: boolean;
    // The input area is turn-driven, in priority order: while you may still post (canSend)
    // the message field + send show; once your one allowed message is sent a short caption
    // replaces them until the next turn (myTurn); on the opponent's turn of an active game
    // the nudge button shows (canNudge) — disabled with an "awaiting reply" caption while the
    // hourly cooldown is active; a finished game offers nothing (it is read-only).
    myTurn?: boolean;
    // canSend is true while the player may still post this turn (own turn and the per-turn
    // limit not yet reached); it gates the message field.
    canSend?: boolean;
    // canNudge is true on the opponent's turn of an active game; it gates the nudge button
    // (nudging your own turn or a finished game makes no sense).
    canNudge?: boolean;
    // waiting is true while an auto-match game still has no opponent: both send and nudge
    // are disabled (there is no one to message or hurry yet).
    waiting?: boolean;
    nudgeOnCooldown?: boolean;
    // vsAi disables both controls in an honest-AI game: the opponent is a robot, so there is
    // nobody to message or hurry. The fields still show (turn-driven), but disabled.
    vsAi?: boolean;
    // blocked hides the whole composer (message field, send and nudge), leaving only the chat
    // log — as in a finished game — when no opponent can be reached: the viewer has blocked them
    // (the backend rejects it too), or their account has been deleted.
    blocked?: boolean;
    onsend: (text: string) => void;
    onnudge: () => void;
  } = $props();

  let text = $state('');

  function send() {
    const v = text.trim();
    if (!v) return;
    onsend(v);
    text = '';
  }
</script>

<div class="chat">
  <div class="list">
    {#if messages.length === 0}
      <p class="empty">{t('chat.empty')}</p>
    {/if}
    {#each messages as m (m.id)}
      {#if m.kind === 'nudge'}
        <div class="note" class:mine={m.senderId === myId}>{t('chat.nudge')}</div>
      {:else}
        <div class="msg" class:mine={m.senderId === myId}>{m.body}</div>
      {/if}
    {/each}
  </div>
  {#if !blocked}
  <div class="input">
    {#if canSend}
      <input
        maxlength="60"
        placeholder={t('chat.placeholder')}
        bind:value={text}
        disabled={vsAi}
        onkeydown={(e) => e.key === 'Enter' && !busy && !vsAi && send()}
      />
      <button class="iconbtn" onclick={send} disabled={busy || waiting || vsAi || !connection.online} aria-label={t('chat.send')}>⬆️</button>
    {:else if myTurn}
      <!-- Own turn, the one allowed message already sent: a caption holds the row until the
           next turn (no nudge — there is no one to hurry on your own turn). -->
      <span class="cooldown">{t('chat.sentThisTurn')}</span>
    {:else if canNudge}
      <!-- A flex:1 caption keeps the nudge pinned right whether or not the cooldown text shows. -->
      <span class="cooldown">{nudgeOnCooldown ? t('chat.awaitingReply') : ''}</span>
      <button class="iconbtn" onclick={onnudge} disabled={busy || waiting || nudgeOnCooldown || vsAi || !connection.online} aria-label={t('chat.nudgeAction')}>🛎️</button>
    {/if}
  </div>
  {/if}
</div>

<style>
  .chat {
    display: flex;
    flex-direction: column;
    gap: 10px;
    /* Fill the chat screen; the list scrolls and the input pins to the bottom. The screen
       fits the visual viewport (--vvh), so an open keyboard simply shrinks it and the input
       stays visible — no modal relayout, no page jump. */
    flex: 1;
    min-height: 0;
    padding: 10px var(--pad);
    box-sizing: border-box;
  }
  .list {
    flex: 1;
    overflow: auto;
    display: flex;
    flex-direction: column;
    gap: 6px;
    padding: 4px;
  }
  .empty {
    color: var(--text-muted);
    text-align: center;
    margin: auto;
  }
  .msg {
    align-self: flex-start;
    max-width: 80%;
    padding: 7px 11px;
    border-radius: 12px;
    background: var(--surface-2);
  }
  .msg.mine {
    align-self: flex-end;
    background: var(--accent);
    color: var(--accent-text);
  }
  .note {
    /* A nudge aligns by sender, like a chat bubble: the opponent's hurry-up reads from the
       left, your own from the right — only the alignment changes, the muted italic stays. */
    align-self: flex-start;
    font-size: 0.82rem;
    color: var(--text-muted);
    font-style: italic;
  }
  .note.mine {
    align-self: flex-end;
  }
  .input {
    display: flex;
    gap: 6px;
    align-items: center;
  }
  /* The cooldown caption sits to the left of the disabled nudge button. */
  .cooldown {
    flex: 1;
    text-align: right;
    color: var(--text-muted);
    font-size: 0.85rem;
  }
  .input input {
    flex: 1;
    min-width: 0;
    padding: 10px;
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    background: var(--bg);
    color: var(--text);
  }
  .iconbtn {
    flex: 0 0 auto;
    padding: 8px 12px;
    border: 1px solid var(--border);
    background: var(--surface);
    color: var(--text);
    border-radius: var(--radius-sm);
    font-size: 1.25rem;
    line-height: 1;
  }
  .iconbtn:disabled {
    opacity: 0.45;
  }
</style>
