import { api, type User, type LoginResponse } from '$lib/api/client';
import { putMyTimezone } from '$lib/api/me';
import { queryClient } from '$lib/query/client';
import { signalSessionEnd } from './sessionEnd.svelte';
import { user, setUser } from './user.svelte';

// Re-export so existing `import { user } from '$lib/auth/store.svelte'`
// callers keep working. New code can import directly from auth/user.svelte.
export { user };

// Weekly client-driven cadence for sending the browser's current IANA
// timezone to PUT /api/me/timezone (#392 Half B). Tracked in
// localStorage so the cadence survives tab restarts; bumped after each
// successful PUT. Failures are swallowed — server keeps its previous
// value (or 'UTC' default).
const TZ_LAST_SENT_KEY = 'minstrel.tz_last_sent_at';
const WEEKLY_MS = 7 * 24 * 60 * 60 * 1000;

async function sendTimezoneIfStale(): Promise<void> {
  if (typeof window === 'undefined') return; // SSR-safe no-op
  try {
    const tz = Intl.DateTimeFormat().resolvedOptions().timeZone;
    if (!tz) return;
    const lastStr = window.localStorage.getItem(TZ_LAST_SENT_KEY);
    const last = lastStr ? Number(lastStr) : 0;
    if (Number.isFinite(last) && Date.now() - last < WEEKLY_MS) return;
    await putMyTimezone(tz);
    window.localStorage.setItem(TZ_LAST_SENT_KEY, String(Date.now()));
  } catch (err) {
    console.warn('tz send failed:', err);
  }
}

export async function bootstrap(): Promise<void> {
  try {
    setUser(await api.get<User>('/api/me'));
    // ignore: best-effort, runs in background
    void sendTimezoneIfStale();
  } catch {
    setUser(null);
  }
}

export async function login(username: string, password: string): Promise<void> {
  const res = await api.post<LoginResponse>('/api/auth/login', { username, password });
  setUser(res.user);
  void sendTimezoneIfStale();
}

export async function register(opts: {
  username: string;
  password: string;
  inviteToken?: string;
  displayName?: string;
}): Promise<void> {
  const body: Record<string, string> = {
    username: opts.username,
    password: opts.password,
  };
  if (opts.inviteToken) body.invite_token = opts.inviteToken;
  if (opts.displayName) body.display_name = opts.displayName;
  const res = await api.post<LoginResponse>('/api/auth/register', body);
  setUser(res.user);
  await bootstrap();
  void sendTimezoneIfStale();
}

export async function forgotPassword(email: string): Promise<void> {
  await api.post('/api/auth/forgot-password', { email });
}

export async function resetPassword(token: string, newPassword: string): Promise<void> {
  await api.post('/api/auth/reset-password', { token, new_password: newPassword });
}

export async function logout(opts: { silent?: boolean } = {}): Promise<void> {
  const userId = user.value?.id;
  if (!opts.silent) {
    try {
      await api.post('/api/auth/logout', {});
    } catch {
      // best effort — server-side session may already be gone
    }
  }
  signalSessionEnd(userId ?? null);
  setUser(null);
  queryClient.clear();
}
