<script lang="ts">
  import { onMount } from 'svelte';
  import Screen from '../components/Screen.svelte';
  import Chat from './Chat.svelte';
  import { gateway } from '../lib/gateway';
  import { app, handleError, clearChatUnread } from '../lib/app.svelte';
  import { t } from '../lib/i18n/index.svelte';
  import type { ChatMessage, StateView } from '../lib/model';

  // The chat is its own screen (Stage 17), so the soft keyboard simply resizes the viewport with
  // the input pinned to the bottom — no modal relayout jank. It loads the game state (for the
  // turn-based chat/nudge toggle) and the message list, and clears the unread badge while open.
  let { id }: { id: string } = $props();

  let view = $state<StateView | null>(null);
  let messages = $state<ChatMessage[]>([]);
  let busy = $state(false);
  let tick = $state(0);

  const myId = $derived(app.session?.userId ?? '');
  const isMyTurn = $derived(!!view && view.game.status === 'active' && view.game.toMove === view.seat);
  const nudgeCooldownSecs = 3600;
  // The nudge is one-per-hour-per-game and clears once the player chats (engagement); the
  // backend stays authoritative, so a move-based reset is left to it.
  const nudgeOnCooldown = $derived.by(() => {
    void tick;
    let lastNudge = 0;
    let lastChat = 0;
    for (const m of messages) {
      if (m.senderId !== myId) continue;
      if (m.kind === 'nudge') lastNudge = Math.max(lastNudge, m.createdAtUnix);
      else lastChat = Math.max(lastChat, m.createdAtUnix);
    }
    if (lastNudge === 0 || Date.now() / 1000 - lastNudge >= nudgeCooldownSecs) return false;
    return lastChat <= lastNudge;
  });

  async function refresh() {
    try {
      messages = await gateway.chatList(id);
      clearChatUnread(id);
    } catch {
      /* best-effort */
    }
  }
  onMount(async () => {
    try {
      view = await gateway.gameState(id, false);
    } catch (e) {
      handleError(e);
    }
    await refresh();
  });

  // Live: refresh (and keep the unread cleared) on a chat / nudge for this game.
  $effect(() => {
    const e = app.lastEvent;
    if (!e) return;
    if ((e.kind === 'chat_message' && e.message.gameId === id) || (e.kind === 'nudge' && e.gameId === id)) {
      void refresh();
    }
  });
  // Re-evaluate the nudge cooldown on a timer so the control re-enables on time.
  $effect(() => {
    const h = setInterval(() => (tick += 1), 20000);
    return () => clearInterval(h);
  });

  async function sendChat(text: string) {
    busy = true;
    try {
      messages = [...messages, await gateway.chatPost(id, text)];
    } catch (e) {
      handleError(e);
    } finally {
      busy = false;
    }
  }
  async function nudge() {
    busy = true;
    try {
      messages = [...messages, await gateway.nudge(id)];
    } catch (e) {
      handleError(e);
    } finally {
      busy = false;
    }
  }
</script>

<Screen title={t('game.chat')} back={`/game/${id}`} scroll={false} column>
  <Chat {messages} {myId} {busy} myTurn={isMyTurn} {nudgeOnCooldown} onsend={sendChat} onnudge={nudge} />
</Screen>
