import { LoginCredentials, SignupCredentials, User, AuthError, AuthErrorCode } from '../types/auth.types';
import { sanitizeInput, generateCSRFToken, encryptData } from '../utils/security';

const API_BASE_URL = process.env.REACT_APP_API_URL || 'http://localhost:3000/api';
const TOKEN_KEY = 'auth_token';
const REFRESH_TOKEN_KEY = 'refresh_token';

export class AuthService {
  private static readonly csrfToken = generateCSRFToken();
  private static readonly maxRetries = 2;
  private static readonly requestTimeout = 15000;

  private static async makeRequest<T>(
    endpoint: string,
    method: string,
    data?: unknown,
    retryCount = 0
  ): Promise<T> {
    const token = localStorage.getItem(TOKEN_KEY);
    const headers = new Headers({
      'Content-Type': 'application/json',
      'X-CSRF-Token': this.csrfToken,
      'X-Requested-With': 'XMLHttpRequest',
      ...(token && { Authorization: `Bearer ${encryptData(token)}` })
    });

    const controller = new AbortController();
    const timeoutId = setTimeout(() => controller.abort(), this.requestTimeout);

    try {
      const response = await fetch(`${API_BASE_URL}${endpoint}`, {
        method,
        headers,
        credentials: 'include',
        body: data ? JSON.stringify(data) : undefined,
        signal: controller.signal,
      });

      if (response.status === 401 && retryCount < this.maxRetries) {
        await this.refreshToken();
        return this.makeRequest(endpoint, method, data, retryCount + 1);
      }

      if (!response.ok) {
        const error = await response.json();
        throw this.createAuthError(error, response.status);
      }

      return response.json();
    } catch (error) {
      throw this.handleError(error);
    } finally {
      clearTimeout(timeoutId);
    }
  }

  private static createAuthError(error: any, statusCode?: number): AuthError {
    return {
      code: error.code as AuthErrorCode || 'SERVER_ERROR',
      message: error.message || 'An unexpected error occurred',
      details: error.details,
      timestamp: new Date().toISOString(),
      statusCode
    };
  }

  private static handleError(error: any): AuthError {
    if (error.name === 'AbortError') {
      return this.createAuthError({
        code: 'REQUEST_FAILED',
        message: 'Request timeout'
      });
    }
    if (error instanceof TypeError) {
      return this.createAuthError({
        code: 'NETWORK_ERROR',
        message: 'Network connection failed'
      });
    }
    return error;
  }

  static async login(credentials: LoginCredentials): Promise<User> {
    const sanitizedCredentials = {
      email: sanitizeInput(credentials.email.toLowerCase()),
      password: await encryptData(credentials.password),
      rememberMe: credentials.rememberMe
    };

    const response = await this.makeRequest<{ user: User; token: string; refreshToken: string }>(
      '/auth/login',
      'POST',
      sanitizedCredentials
    );

    this.setTokens(response.token, response.refreshToken);
    return response.user;
  }

  private static setTokens(token: string, refreshToken: string): void {
    localStorage.setItem(TOKEN_KEY, encryptData(token));
    localStorage.setItem(REFRESH_TOKEN_KEY, encryptData(refreshToken));
  }

  // ... rest of the methods with similar improvements ...
}