"use client";

import { createPlatformAdapter } from "../platform/adapter";

export interface StoredTokens {
  accessToken: string;
  refreshToken: string;
  expiresIn: number;
}

// Token storage goes through the PlatformAdapter (§4.9), which picks the OS
// keychain when running inside the Tauri shell (Feature 11.9) and
// IndexedDB + localStorage on web/PWA — the call sites here never know which.
const adapter = createPlatformAdapter();
const KEY = "slackwsh.tokens";

/** Mirror in localStorage so a hard refresh still sees the session even if
 * IndexedDB is slow or briefly unavailable (private mode quirks, etc.). */
const LOCAL_KEY = "slackwsh.tokens.v1";

function readLocal(): StoredTokens | null {
  if (typeof window === "undefined") return null;
  try {
    const raw = window.localStorage.getItem(LOCAL_KEY);
    return raw ? (JSON.parse(raw) as StoredTokens) : null;
  } catch {
    return null;
  }
}

function writeLocal(tokens: StoredTokens | null) {
  if (typeof window === "undefined") return;
  try {
    if (!tokens) window.localStorage.removeItem(LOCAL_KEY);
    else window.localStorage.setItem(LOCAL_KEY, JSON.stringify(tokens));
  } catch {
    // Quota / private mode — secure store is still attempted.
  }
}

export async function getTokens(): Promise<StoredTokens | null> {
  const fromLocal = readLocal();
  if (fromLocal?.accessToken && fromLocal?.refreshToken) return fromLocal;

  try {
    const raw = await adapter.secureStorage.get(KEY);
    if (!raw) return null;
    const tokens = JSON.parse(raw) as StoredTokens;
    writeLocal(tokens);
    return tokens;
  } catch {
    return fromLocal;
  }
}

export async function setTokens(tokens: StoredTokens): Promise<void> {
  writeLocal(tokens);
  try {
    await adapter.secureStorage.set(KEY, JSON.stringify(tokens));
  } catch {
    // localStorage already holds the session for this browser profile.
  }
}

export async function clearTokens(): Promise<void> {
  writeLocal(null);
  try {
    await adapter.secureStorage.remove(KEY);
  } catch {
    // ignore
  }
}

/** True when we have a refreshable session (access may be expired). */
export async function hasSession(): Promise<boolean> {
  const tokens = await getTokens();
  return Boolean(tokens?.refreshToken);
}
