import * as SecureStore from 'expo-secure-store';
import { AuthDb } from './database';
import { getConfiguredBackendRootUrl } from '../utils/backendUrl';

const SESSION_KEY = 'greenlens_session_v3';

export interface AuthSession {
  userId: number;       // local SQLite id (for plants/settings queries)
  serverUserId: string; // server-side user id (in JWT)
  email: string;
  name: string;
  token: string;        // JWT from server
  loggedInAt: string;
}

// ─── Internal helpers ──────────────────────────────────────────────────────

const clearStoredSession = async (): Promise<void> => {
  await SecureStore.deleteItemAsync(SESSION_KEY);
};

const authPost = async (path: string, body: object): Promise<{ userId: string; email: string; name: string; token: string }> => {
  const backendUrl = getConfiguredBackendRootUrl();
  const hasBackendUrl = Boolean(backendUrl);
  const url = hasBackendUrl ? `${backendUrl}${path}` : path;
  let response: Response;
  try {
    response = await fetch(url, {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify(body),
    });
  } catch (e) {
    if (!hasBackendUrl) {
      throw new Error('BACKEND_URL_MISSING');
    }
    throw new Error('NETWORK_ERROR');
  }
  const data = await response.json().catch(() => ({}));
  if (!response.ok) {
    const code = (data as any).code || 'AUTH_ERROR';
    const msg = (data as any).message || '';
    console.warn(`[Auth] ${path} failed:`, response.status, code, msg);
    throw new Error(code);
  }
  return data as any;
};

const buildSession = (data: { userId: string; email: string; name: string; token: string }): AuthSession => {
  const localUser = AuthDb.ensureLocalUser(data.email, data.name);
  return {
    userId: localUser.id,
    serverUserId: data.userId,
    email: data.email,
    name: data.name,
    token: data.token,
    loggedInAt: new Date().toISOString(),
  };
};

// ─── AuthService ───────────────────────────────────────────────────────────

export const AuthService = {
  async getSession(): Promise<AuthSession | null> {
    try {
      const raw = await SecureStore.getItemAsync(SESSION_KEY);
      if (!raw) return null;
      const parsed = JSON.parse(raw) as Partial<AuthSession>;
      if (!parsed.token || !parsed.serverUserId || !parsed.userId) {
        await clearStoredSession();
        return null;
      }
      return parsed as AuthSession;
    } catch {
      await clearStoredSession();
      return null;
    }
  },

  async signUp(email: string, name: string, password: string): Promise<AuthSession> {
    const data = await authPost('/auth/signup', { email, name, password });
    const session = buildSession(data);
    await SecureStore.setItemAsync(SESSION_KEY, JSON.stringify(session));
    return session;
  },

  async login(email: string, password: string): Promise<AuthSession> {
    const data = await authPost('/auth/login', { email, password });
    const session = buildSession(data);
    await SecureStore.setItemAsync(SESSION_KEY, JSON.stringify(session));
    return session;
  },

  async logout(): Promise<void> {
    await clearStoredSession();
  },

  async updateSessionName(name: string): Promise<void> {
    const session = await this.getSession();
    if (!session) return;
    await SecureStore.setItemAsync(SESSION_KEY, JSON.stringify({ ...session, name }));
  },

  async validateWithServer(): Promise<'valid' | 'invalid' | 'unreachable'> {
    const session = await this.getSession();
    if (!session) return 'invalid';
    const backendUrl = getConfiguredBackendRootUrl();
    if (!backendUrl) return 'unreachable';
    try {
      const response = await fetch(`${backendUrl}/v1/billing/summary`, {
        headers: { Authorization: `Bearer ${session.token}` },
      });
      if (response.status === 401 || response.status === 403) return 'invalid';
      return 'valid';
    } catch {
      return 'unreachable';
    }
  },

  async checkIfFirstRun(): Promise<boolean> {
    const flag = await SecureStore.getItemAsync('greenlens_first_run_complete');
    return flag !== 'true';
  },

  async markFirstRunComplete(): Promise<void> {
    await SecureStore.setItemAsync('greenlens_first_run_complete', 'true');
  },

  async clearAllData(): Promise<void> {
    await clearStoredSession();
    await SecureStore.deleteItemAsync('greenlens_first_run_complete');
    // Note: SQLite tables aren't cleared here to avoid destroying user data 
    // without explicit consent, but session tokens are wiped.
  },
};
