import { ActivityLogger } from "./activity-logger";

interface AuthToken {
  token: string;
  expiresAt: number;
}

class OpenWebAuth {
  private static instance: OpenWebAuth;
  private cachedToken: AuthToken | null = null;
  private readonly baseUrl = 'http://api.openweb.live:3000';
  private readonly username: string;
  private readonly password: string;

  private constructor() {
    // Use environment variables or fallback to the provided credentials
    this.username = process.env.OPENWEB_API_USERNAME || 'admin';
    this.password = process.env.OPENWEB_API_PASSWORD || 'Aq9v!dZp#F2nK3wY';
    
    if (!this.username || !this.password) {
      console.error('OpenWeb API credentials not configured');
      throw new Error('OpenWeb API credentials not configured');
    }
    
    console.log(`[OpenWeb Auth] Initialized with username: ${this.username}`);
  }

  public static getInstance(): OpenWebAuth {
    if (!OpenWebAuth.instance) {
      OpenWebAuth.instance = new OpenWebAuth();
    }
    return OpenWebAuth.instance;
  }

  private async authenticate(): Promise<string> {
    try {
      console.log('[OpenWeb Auth] Authenticating with OpenWeb API...');
      
      const response = await fetch(`${this.baseUrl}/auth/login`, {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
        },
        body: JSON.stringify({
          username: this.username,
          password: this.password
        })
      });

      if (!response.ok) {
        const errorText = await response.text();
        console.error(`[OpenWeb Auth] Authentication failed: ${response.status} ${response.statusText}`, errorText);
        throw new Error(`OpenWeb API authentication failed: ${response.status} ${response.statusText}`);
      }

      const data = await response.json();
      
      if (!data.data || !data.data.token) {
        console.error('[OpenWeb Auth] No token in authentication response:', data);
        throw new Error('No token received from OpenWeb API');
      }

      // Cache token with 23 hour expiry (OpenWeb tokens last 24h, refresh 1h early for safety)
      this.cachedToken = {
        token: data.data.token,
        expiresAt: Date.now() + (23 * 60 * 60 * 1000) // 23 hours
      };

      console.log('[OpenWeb Auth] Successfully authenticated with OpenWeb API');
      return data.data.token;
      
    } catch (error) {
      console.error('[OpenWeb Auth] Authentication error:', error);
      throw error;
    }
  }

  public async getValidToken(): Promise<string> {
    // Check if we have a valid cached token
    if (this.cachedToken && this.cachedToken.expiresAt > Date.now()) {
      return this.cachedToken.token;
    }

    // Token expired or doesn't exist, get a new one
    return await this.authenticate();
  }

  public async makeAuthenticatedRequest(url: string, options: RequestInit = {}): Promise<Response> {
    try {
      const token = await this.getValidToken();
      
      const authenticatedOptions: RequestInit = {
        ...options,
        headers: {
          ...options.headers,
          'Authorization': `Bearer ${token}`,
          'Content-Type': 'application/json',
        }
      };

      console.log(`[OpenWeb Auth] Making authenticated request to: ${url}`);
      const response = await fetch(url, authenticatedOptions);
      
      // If we get a 401, the token might be expired, try refreshing once
      if (response.status === 401) {
        console.log('[OpenWeb Auth] Received 401, refreshing token and retrying...');
        this.cachedToken = null; // Clear cached token
        const newToken = await this.getValidToken();
        
        authenticatedOptions.headers = {
          ...authenticatedOptions.headers,
          'Authorization': `Bearer ${newToken}`,
        };
        
        const retryResponse = await fetch(url, authenticatedOptions);
        console.log(`[OpenWeb Auth] Retry response status: ${retryResponse.status}`);
        return retryResponse;
      }
      
      console.log(`[OpenWeb Auth] Request completed with status: ${response.status}`);
      return response;
      
    } catch (error) {
      console.error('[OpenWeb Auth] Request failed:', error);
      throw error;
    }
  }

  public clearToken(): void {
    this.cachedToken = null;
    console.log('[OpenWeb Auth] Token cache cleared');
  }
  
  public getTokenStatus(): { hasToken: boolean; expiresIn?: number; expiresAt?: Date } {
    if (!this.cachedToken) {
      return { hasToken: false };
    }
    
    const now = Date.now();
    const expiresIn = Math.max(0, this.cachedToken.expiresAt - now);
    
    return {
      hasToken: true,
      expiresIn: Math.round(expiresIn / 1000), // seconds until expiry
      expiresAt: new Date(this.cachedToken.expiresAt)
    };
  }
  
  public async testAuthentication(): Promise<boolean> {
    try {
      console.log('[OpenWeb Auth] Testing authentication...');
      await this.getValidToken();
      console.log('[OpenWeb Auth] Authentication test successful');
      return true;
    } catch (error) {
      console.error('[OpenWeb Auth] Authentication test failed:', error);
      return false;
    }
  }
}

export default OpenWebAuth;