/**
 * Bulk Operations API Service
 * 
 * Handles mass operations on multiple machines:
 * - Health checks
 * - SSH command execution (future)
 * - Multi-connect (future)
 */

import { API_CONFIG } from '../config/api';
import { authService } from './auth-service';

// ========================================================================================
// Constants
// ========================================================================================

const DEFAULT_TIMEOUT = {
  HEALTH_CHECK: 5, // seconds
  SSH_COMMAND: 30, // seconds
} as const;

const HTTP_STATUS = {
  FORBIDDEN: 403,
} as const;

const ROLE_LIMITS = {
  GUEST: { maxHealthCheck: 10, maxSSHCommand: 0 },
  USER: { maxHealthCheck: 50, maxSSHCommand: 20 },
  ADMIN: { maxHealthCheck: 200, maxSSHCommand: 100 },
  SUPER_ADMIN: { maxHealthCheck: 200, maxSSHCommand: 100 },
} as const;

const DEFAULT_CHECK_PORT = true;

// ========================================================================================
// Types
// ========================================================================================

export type HealthCheckStatus = 'success' | 'failed' | 'timeout';
export type SSHCommandStatus = 'success' | 'failed' | 'timeout' | 'no_credentials';
export type CredentialsMode = 'global' | 'custom';
export type UserRole = keyof typeof ROLE_LIMITS;

export interface BulkHealthCheckRequest {
  machine_ids: string[];
  timeout?: number;
  check_port?: boolean;
}

export interface BulkHealthCheckResult {
  machine_id: string;
  machine_name: string;
  hostname: string;
  status: HealthCheckStatus;
  available: boolean;
  response_time_ms?: number;
  error?: string;
  checked_at: string;
}

export interface BulkHealthCheckResponse {
  total: number;
  success: number;
  failed: number;
  available: number;
  unavailable: number;
  results: BulkHealthCheckResult[];
  execution_time_ms: number;
  started_at: string;
  completed_at: string;
}

// SSH Command Types
export interface SSHCredentials {
  username: string;
  password: string;
}

export interface BulkSSHCommandRequest {
  machine_ids: string[];
  machine_hostnames?: Record<string, string>;  // For non-saved machines
  command: string;
  credentials_mode: CredentialsMode;
  global_credentials?: SSHCredentials;
  machine_credentials?: Record<string, SSHCredentials>;
  timeout?: number;
}

export interface BulkSSHCommandResult {
  machine_id: string;
  machine_name: string;
  hostname: string;
  status: SSHCommandStatus;
  exit_code?: number;
  stdout?: string;
  stderr?: string;
  error?: string;
  execution_time_ms?: number;
  executed_at: string;
}

export interface BulkSSHCommandResponse {
  total: number;
  success: number;
  failed: number;
  results: BulkSSHCommandResult[];
  execution_time_ms: number;
  command: string;
  started_at: string;
  completed_at: string;
}

// ========================================================================================
// API Service
// ========================================================================================

class BulkOperationsApiService {
  
  /**
   * Bulk machine availability check
   * 
   * Role-based limits:
   * - GUEST: max 10 machines
   * - USER: max 50 machines
   * - ADMIN: max 200 machines
   */
  async bulkHealthCheck(request: BulkHealthCheckRequest): Promise<BulkHealthCheckResponse> {
    try {
      const token = await authService.getToken();
      
      if (!token) {
        throw new Error('Authentication token not found. Please log in again.');
      }

      const response = await fetch(`${API_CONFIG.BASE_URL}${API_CONFIG.ENDPOINTS.BULK.HEALTH_CHECK}`, {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
          'Authorization': `Bearer ${token}`
        },
        body: JSON.stringify({
          machine_ids: request.machine_ids,
          timeout: request.timeout ?? DEFAULT_TIMEOUT.HEALTH_CHECK,
          check_port: request.check_port ?? DEFAULT_CHECK_PORT
        })
      });

      if (!response.ok) {
        const errorData = await response.json().catch(() => ({ detail: 'Unknown error' }));
        
        if (response.status === HTTP_STATUS.FORBIDDEN) {
          throw new Error(errorData.detail || 'Permission denied. Check role-based limits.');
        }
        
        throw new Error(errorData.detail || `Request failed with status ${response.status}`);
      }

      const data: BulkHealthCheckResponse = await response.json();
      return data;

    } catch (error) {
      if (error instanceof Error) {
        throw error;
      }
      throw new Error('Failed to perform bulk health check');
    }
  }

  /**
   * Bulk SSH command execution
   * 
   * Role-based limits:
   * - GUEST: forbidden
   * - USER: max 20 machines, whitelist commands only
   * - ADMIN: max 100 machines, any commands
   */
  async bulkSSHCommand(request: BulkSSHCommandRequest): Promise<BulkSSHCommandResponse> {
    try {
      const token = await authService.getToken();
      
      if (!token) {
        throw new Error('Authentication token not found. Please log in again.');
      }

      const response = await fetch(`${API_CONFIG.BASE_URL}${API_CONFIG.ENDPOINTS.BULK.SSH_COMMAND}`, {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
          'Authorization': `Bearer ${token}`
        },
        body: JSON.stringify({
          machine_ids: request.machine_ids,
          machine_hostnames: request.machine_hostnames,
          command: request.command,
          credentials_mode: request.credentials_mode,
          global_credentials: request.global_credentials,
          machine_credentials: request.machine_credentials,
          timeout: request.timeout ?? DEFAULT_TIMEOUT.SSH_COMMAND
        })
      });

      if (!response.ok) {
        const errorData = await response.json().catch(() => ({ detail: 'Unknown error' }));
        
        if (response.status === HTTP_STATUS.FORBIDDEN) {
          throw new Error(errorData.detail || 'Permission denied. Check role and command whitelist.');
        }
        
        throw new Error(errorData.detail || `Request failed with status ${response.status}`);
      }

      const data: BulkSSHCommandResponse = await response.json();
      return data;

    } catch (error) {
      if (error instanceof Error) {
        throw error;
      }
      throw new Error('Failed to execute bulk SSH command');
    }
  }

  /**
   * Get role-based limit for bulk operations
   */
  getRoleLimits(role: string): { maxHealthCheck: number; maxSSHCommand: number } {
    return ROLE_LIMITS[role as UserRole] || ROLE_LIMITS.GUEST;
  }
}

export const bulkOperationsApi = new BulkOperationsApiService();

