import {
  atomWithLocalStorage,
  getLocalStorageItem,
  setLocalStorageItem,
} from './utils/atomWithLocalStorage';

// Persisted geometry of the desktop/tablet floating media window
// (`RoomViewMediaWindow`). Position + size survive reloads; both are
// re-clamped into the live viewport on open so a window saved on a big
// monitor can't open off-screen on a small one. `null` until the user
// has opened the viewer once — the component then centres a default.
export const MEDIA_WINDOW_RECT_KEY = 'vojo_media_window_rect';

export type MediaWindowRect = { x: number; y: number; w: number; h: number };

// Floors so the window never collapses below a usable media card.
export const MEDIA_WINDOW_MIN_W = 320;
export const MEDIA_WINDOW_MIN_H = 240;
// Always keep at least this much of the window on-screen so the drag
// bar stays grabbable no matter where it was dropped.
const ON_SCREEN_MARGIN_PX = 80;

const isFiniteNumber = (v: unknown): v is number => typeof v === 'number' && Number.isFinite(v);

const readMediaWindowRect = (key: string): MediaWindowRect | null => {
  const raw = getLocalStorageItem<unknown>(key, null);
  if (!raw || typeof raw !== 'object') return null;
  const r = raw as Partial<MediaWindowRect>;
  if (
    !isFiniteNumber(r.x) ||
    !isFiniteNumber(r.y) ||
    !isFiniteNumber(r.w) ||
    !isFiniteNumber(r.h)
  ) {
    return null;
  }
  return { x: r.x, y: r.y, w: r.w, h: r.h };
};

export const mediaWindowRectAtom = atomWithLocalStorage<MediaWindowRect | null>(
  MEDIA_WINDOW_RECT_KEY,
  readMediaWindowRect,
  setLocalStorageItem
);

// Pleasant centred default — roughly half the width, ~70% of the height
// of a typical desktop, clamped to the floors.
export const defaultMediaWindowRect = (vw: number, vh: number): MediaWindowRect => {
  const w = Math.round(Math.min(640, Math.max(MEDIA_WINDOW_MIN_W, vw * 0.45)));
  const h = Math.round(Math.min(Math.round(vh * 0.85), Math.max(MEDIA_WINDOW_MIN_H, vh * 0.7)));
  return { x: Math.round((vw - w) / 2), y: Math.round((vh - h) / 2), w, h };
};

// Clamp a rect into the viewport: size capped to the viewport and floored,
// position kept so a margin always stays on-screen (drag bar grabbable).
export const clampMediaWindowRect = (
  rect: MediaWindowRect,
  vw: number,
  vh: number
): MediaWindowRect => {
  const w = Math.round(Math.max(MEDIA_WINDOW_MIN_W, Math.min(rect.w, vw)));
  const h = Math.round(Math.max(MEDIA_WINDOW_MIN_H, Math.min(rect.h, vh)));
  const x = Math.round(
    Math.max(ON_SCREEN_MARGIN_PX - w, Math.min(rect.x, vw - ON_SCREEN_MARGIN_PX))
  );
  const y = Math.round(Math.max(0, Math.min(rect.y, Math.max(0, vh - 40))));
  return { x, y, w, h };
};
