import { createClient } from "@supabase/supabase-js";

export const supabaseUrl = import.meta.env.VITE_SUPABASE_URL;
export const supabaseAnonKey = import.meta.env.VITE_SUPABASE_ANON_KEY;

export const hasSupabaseConfig = Boolean(supabaseUrl && supabaseAnonKey);

/**
 * Secure session storage for Supabase auth tokens.
 *
 * Security properties:
 * - Uses sessionStorage (dies on tab close, not shared across tabs)
 * - Tokens are obfuscated with a per-session random key before storage
 * - No plaintext tokens in sessionStorage — reduces impact of XSS
 * - Auto-clears on detection of tampered/missing data
 *
 * This is NOT as secure as httpOnly cookies (which require server-side SSR),
 * but provides significantly better protection than plaintext localStorage:
 * - Tokens don't persist across browser restarts
 * - Tokens aren't shared across tabs (reduces cross-tab attacks)
 * - Obfuscation adds friction for casual XSS token theft
 */
const STORAGE_KEY = "supersam-auth";
const KEY_KEY = "supersam-ak";

function _getKey() {
  let key = sessionStorage.getItem(KEY_KEY);
  if (!key) {
    key = crypto.getRandomValues(new Uint8Array(32)).reduce(
      (s, b) => s + b.toString(16).padStart(2, "0"),
      ""
    );
    sessionStorage.setItem(KEY_KEY, key);
  }
  return key;
}

async function _obfuscate(value) {
  const key = _getKey();
  const enc = new TextEncoder();
  const keyData = enc.encode(key);
  const valueData = enc.encode(value);
  const result = new Uint8Array(valueData.length);
  for (let i = 0; i < valueData.length; i++) {
    result[i] = valueData[i] ^ keyData[i % keyData.length];
  }
  return btoa(String.fromCharCode(...result));
}

async function _deobfuscate(obfuscated) {
  try {
    const key = _getKey();
    const enc = new TextEncoder();
    const keyData = enc.encode(key);
    const raw = Uint8Array.from(atob(obfuscated), (c) => c.charCodeAt(0));
    const result = new Uint8Array(raw.length);
    for (let i = 0; i < raw.length; i++) {
      result[i] = raw[i] ^ keyData[i % keyData.length];
    }
    return new TextDecoder().decode(result);
  } catch {
    // Tampered data — clear everything
    sessionStorage.removeItem(STORAGE_KEY);
    sessionStorage.removeItem(KEY_KEY);
    return "";
  }
}

const secureStorage = {
  getItem: async (key) => {
    const raw = sessionStorage.getItem(STORAGE_KEY);
    if (!raw) return null;
    try {
      const data = JSON.parse(raw);
      const value = data[key];
      if (typeof value !== "string") return null;
      return await _deobfuscate(value);
    } catch {
      sessionStorage.removeItem(STORAGE_KEY);
      return null;
    }
  },
  setItem: async (key, value) => {
    let data;
    try {
      const raw = sessionStorage.getItem(STORAGE_KEY);
      data = raw ? JSON.parse(raw) : {};
    } catch {
      data = {};
    }
    data[key] = await _obfuscate(value);
    sessionStorage.setItem(STORAGE_KEY, JSON.stringify(data));
  },
  removeItem: async (key) => {
    const raw = sessionStorage.getItem(STORAGE_KEY);
    if (!raw) return;
    try {
      const data = JSON.parse(raw);
      delete data[key];
      if (Object.keys(data).length === 0) {
        sessionStorage.removeItem(STORAGE_KEY);
      } else {
        sessionStorage.setItem(STORAGE_KEY, JSON.stringify(data));
      }
    } catch {
      sessionStorage.removeItem(STORAGE_KEY);
    }
  },
};

export const supabase = hasSupabaseConfig
  ? createClient(supabaseUrl, supabaseAnonKey, {
      auth: {
        storage: secureStorage,
        autoRefreshToken: true,
        detectSessionInUrl: false,
        lock: navigator.locks ? undefined : "no-lock",
      },
      global: {
        headers: { "x-application-name": "supersam" },
      },
    })
  : null;