import { create } from 'zustand';
import { persist } from 'zustand/middleware';
import type { Character } from '@/lib/schemas';
import type { RosterEntry } from '@/lib/sync/messages';

export type SessionRole = 'off' | 'gm' | 'player';
export type SessionStatus = 'idle' | 'connecting' | 'connected' | 'error';

export interface SeatRequest {
  playerId: string;
  characterId: string;
  offlineSnapshot?: Character;
}

/** Persisted intent to be connected to a room as a player — survives navigation + reload. */
export interface JoinIntent { joinCode: string; password?: string }

interface SessionState {
  role: SessionRole;
  status: SessionStatus;
  roomId: string | null;
  joinCode: string | null;
  error: string | null;
  /** seat-control requests awaiting the GM's approval */
  seatRequests: SeatRequest[];
  /** when set, the app keeps a player connection alive across views/reloads */
  joinIntent: JoinIntent | null;
  /** the player's chosen display name (persisted) */
  guestName: string;
  /** GM only: connected players (for targeting private shares) */
  roster: RosterEntry[];
  set: (patch: Partial<Omit<SessionState, 'set' | 'reset' | 'addSeatRequest' | 'removeSeatRequest' | 'setJoinIntent' | 'setRoster' | 'setGuestName'>>) => void;
  addSeatRequest: (r: SeatRequest) => void;
  removeSeatRequest: (playerId: string) => void;
  setJoinIntent: (j: JoinIntent | null) => void;
  setGuestName: (n: string) => void;
  setRoster: (r: RosterEntry[]) => void;
  reset: () => void;
}

/** Ephemeral session state, EXCEPT joinIntent which is persisted so a player stays
 *  connected across page navigations and reloads. */
export const useSessionStore = create<SessionState>()(
  persist(
    (set) => ({
      role: 'off',
      status: 'idle',
      roomId: null,
      joinCode: null,
      error: null,
      seatRequests: [],
      joinIntent: null,
      guestName: '',
      roster: [],
      set: (patch) => set(patch),
      addSeatRequest: (r) => set((s) => ({ seatRequests: [...s.seatRequests.filter((x) => x.playerId !== r.playerId), r] })),
      removeSeatRequest: (playerId) => set((s) => ({ seatRequests: s.seatRequests.filter((x) => x.playerId !== playerId) })),
      setJoinIntent: (joinIntent) => set({ joinIntent }),
      setGuestName: (guestName) => set({ guestName }),
      setRoster: (roster) => set({ roster }),
      reset: () => set({ role: 'off', status: 'idle', roomId: null, joinCode: null, error: null, seatRequests: [], roster: [] }),
    }),
    { name: 'ttrpg-session', partialize: (s) => ({ joinIntent: s.joinIntent, guestName: s.guestName }) },
  ),
);
