import { getCredentials } from '../config/constants';

export interface AuthStatus {
  isAuthenticated: boolean;
  expiresAt: number | null;
  expiresIn: number | null;
  accessToken: string | null;
  lastError: string | null;
}

class AuthManager {
  private accessToken: string | null = null;
  private expiresAt: number = 0;
  private lastError: string | null = null;
  private listeners: Set<() => void> = new Set();
  private initPromise: Promise<void> | null = null;
  private isReady: boolean = false;
  private profileId: string | null = null;
  private analyticsId: string | null = null;

  async ensureReady(): Promise<boolean> {
    if (this.isReady && this.accessToken) return true;

    if (!this.initPromise) {
      this.initPromise = this.refresh()
        .then(() => { this.isReady = true; })
        .catch((err) => {
          console.error('Initial token fetch failed:', err);
          this.isReady = false;
        });
    }

    await this.initPromise;
    return this.isReady;
  }

  async getToken(): Promise<string> {
    // Refresh if token expires in less than 1 minute
    if (!this.accessToken || Date.now() >= this.expiresAt - 60000) {
      await this.refresh();
    }
    return this.accessToken!;
  }

  private async refresh(): Promise<void> {
    try {
      // Ask the backend for a fresh access token — it manages the refresh token
      const resp = await fetch('/api/auth/token');

      if (!resp.ok) {
        const data = await resp.json().catch(() => ({}));
        throw new Error(data.error || `HTTP ${resp.status}`);
      }

      const data = await resp.json();
      this.accessToken = data.accessToken;
      this.expiresAt = data.expiresAt || (Date.now() + 3500000); // ~58 min fallback
      this.profileId = data.profileId || null;
      this.analyticsId = data.analyticsId || null;
      this.lastError = null;

      this.notifyListeners();
    } catch (err) {
      this.lastError = err instanceof Error ? err.message : 'Unknown error';
      this.notifyListeners();
      throw err;
    }
  }

  async forceRefresh(): Promise<void> {
    this.accessToken = null;
    this.expiresAt = 0;
    this.initPromise = null;
    await this.refresh();
  }

  getProfileId(): string {
    return this.profileId || getCredentials().PROFILE_ID;
  }

  getAnalyticsId(): string {
    return this.analyticsId || getCredentials().EVENT_ANALYTICS_ID;
  }

  isAuthenticated(): boolean {
    return this.accessToken !== null && Date.now() < this.expiresAt;
  }

  getStatus(): AuthStatus {
    const now = Date.now();
    const expiresIn = this.expiresAt > 0 ? Math.floor((this.expiresAt - now) / 1000) : null;
    return {
      isAuthenticated: this.isAuthenticated(),
      expiresAt: this.expiresAt > 0 ? this.expiresAt : null,
      expiresIn: expiresIn && expiresIn > 0 ? expiresIn : null,
      accessToken: this.accessToken,
      lastError: this.lastError,
    };
  }

  subscribe(listener: () => void): () => void {
    this.listeners.add(listener);
    return () => this.listeners.delete(listener);
  }

  private notifyListeners() {
    this.listeners.forEach(listener => listener());
  }
}

export const authManager = new AuthManager();
