import AsyncStorage from '@react-native-async-storage/async-storage';
import { supabase } from './supabase';

// ============================================
// OFFLINE-FIRST AUTH (dummy mode)
// Uses AsyncStorage when Supabase is unreachable.
// Switch USE_OFFLINE to false for real Supabase auth.
// ============================================
const USE_OFFLINE = true;
const USERS_KEY = 'nova40_users';
const SESSION_KEY = 'nova40_session';

// --- Offline helpers ---

function generateUUID() {
  return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => {
    const r = (Math.random() * 16) | 0;
    const v = c === 'x' ? r : (r & 0x3) | 0x8;
    return v.toString(16);
  });
}

function makeUser(email) {
  return {
    id: generateUUID(),
    email,
    email_confirmed_at: new Date().toISOString(),
  };
}

function makeSession(user) {
  return {
    access_token: 'offline_' + user.id,
    user,
  };
}

async function getStoredUsers() {
  const raw = await AsyncStorage.getItem(USERS_KEY);
  return raw ? JSON.parse(raw) : {};
}

async function saveUsers(users) {
  await AsyncStorage.setItem(USERS_KEY, JSON.stringify(users));
}

async function saveSession(session) {
  await AsyncStorage.setItem(SESSION_KEY, JSON.stringify(session));
}

async function clearSession() {
  await AsyncStorage.removeItem(SESSION_KEY);
}

// --- Public API ---

export async function signIn(email, password) {
  if (!USE_OFFLINE) {
    const { data, error } = await supabase.auth.signInWithPassword({ email, password });
    if (error) throw error;
    return data;
  }

  const users = await getStoredUsers();
  const key = email.toLowerCase();
  const stored = users[key];
  if (!stored) throw new Error('No account found with this email. Please register first.');
  if (stored.password !== password) throw new Error('Incorrect password.');

  // Migrate old non-UUID IDs to proper UUIDs
  const uuidRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
  if (!uuidRegex.test(stored.id)) {
    stored.id = generateUUID();
    users[key] = stored;
    await saveUsers(users);
  }

  const user = makeUser(email);
  user.id = stored.id;
  const session = makeSession(user);
  await saveSession(session);
  return { session, user };
}

export async function signUp(email, password) {
  if (!USE_OFFLINE) {
    const { data, error } = await supabase.auth.signUp({ email, password });
    if (error) throw error;
    return data;
  }

  const users = await getStoredUsers();
  const key = email.toLowerCase();
  if (users[key]) throw new Error('An account with this email already exists.');

  const user = makeUser(email);
  users[key] = { id: user.id, password };
  await saveUsers(users);

  // Auto-login (no email confirmation needed)
  const session = makeSession(user);
  await saveSession(session);
  return { session, user };
}

export async function resetPassword(email, newPassword) {
  if (!USE_OFFLINE) {
    // Supabase: send reset email
    const { error } = await supabase.auth.resetPasswordForEmail(email, {
      redirectTo: 'nova40://auth/reset',
    });
    if (error) throw error;
    return { method: 'email' };
  }

  // Offline: reset password directly
  const users = await getStoredUsers();
  const key = email.toLowerCase();
  const stored = users[key];
  if (!stored) throw new Error('No account found with this email.');
  stored.password = newPassword;
  users[key] = stored;
  await saveUsers(users);
  return { method: 'direct' };
}

const OTP_STORE_KEY = 'nova40_pending_otp';

export async function signUpWithPhone(phone, password) {
  if (!USE_OFFLINE) {
    const { data, error } = await supabase.auth.signUp({ phone, password });
    if (error) throw error;
    return data;
  }

  // Offline: store pending registration + generate fake OTP
  const users = await getStoredUsers();
  const key = phone.toLowerCase();
  if (users[key]) throw new Error('An account with this number already exists.');

  const code = String(Math.floor(100000 + Math.random() * 900000));
  await AsyncStorage.setItem(OTP_STORE_KEY, JSON.stringify({ identifier: key, code, password, method: 'phone' }));

  // In real app this would send SMS. For offline, log the code.
  console.log(`[Nova40 OTP] Code for ${phone}: ${code}`);
  return { needsVerification: true };
}

export async function verifyOtp(identifier, code, method) {
  if (!USE_OFFLINE) {
    const verifyPayload = method === 'phone'
      ? { phone: identifier, token: code, type: 'sms' }
      : { email: identifier, token: code, type: 'email' };
    const { data, error } = await supabase.auth.verifyOtp(verifyPayload);
    if (error) throw error;
    return data;
  }

  // Offline: check stored OTP
  const raw = await AsyncStorage.getItem(OTP_STORE_KEY);
  if (!raw) throw new Error('No verification pending. Please register again.');

  const pending = JSON.parse(raw);
  if (pending.identifier !== identifier.toLowerCase()) throw new Error('Identifier mismatch.');
  if (pending.code !== code) throw new Error('Incorrect code. Please try again.');

  // OTP valid — create user
  const users = await getStoredUsers();
  const user = makeUser(identifier);
  users[pending.identifier] = { id: user.id, password: pending.password };
  await saveUsers(users);
  await AsyncStorage.removeItem(OTP_STORE_KEY);

  const session = makeSession(user);
  await saveSession(session);
  return { session, user };
}

export async function signOut() {
  if (!USE_OFFLINE) {
    const { error } = await supabase.auth.signOut();
    if (error) throw error;
    return;
  }
  await clearSession();
}

export async function getSession() {
  if (!USE_OFFLINE) {
    const { data: { session } } = await supabase.auth.getSession();
    return session;
  }

  const raw = await AsyncStorage.getItem(SESSION_KEY);
  return raw ? JSON.parse(raw) : null;
}

export async function signInAsDemo() {
  return signIn('demo@nova40.app', '123456').catch(async () => {
    // Auto-register demo user if not found
    const data = await signUp('demo@nova40.app', '123456');
    return data;
  });
}

export async function signInWithGoogle() {
  if (!USE_OFFLINE) {
    const { data, error } = await supabase.auth.signInWithOAuth({
      provider: 'google',
      options: { redirectTo: 'nova40://auth/callback' },
    });
    if (error) throw error;
    return data;
  }
  throw new Error('Google login is not available in offline mode.');
}

export function onAuthStateChange(callback) {
  if (!USE_OFFLINE) {
    return supabase.auth.onAuthStateChange(callback);
  }
  // Return a no-op subscription for offline mode
  return { data: { subscription: { unsubscribe: () => {} } } };
}
