/**
 * Vultr VPS Provider Implementation
 * API Docs: https://www.vultr.com/api/
 */

import type { VPSProviderConfig, CreateServerRequest, CreateServerResponse } from '../types';
import { VPSProviderBase, OS_IMAGE_MAP } from './vps-provider';

interface VultrInstance {
  id: string;
  os: string;
  ram: number;
  disk: number;
  main_ip: string;
  vcpu_count: number;
  region: string;
  plan: string;
  date_created: string;
  status: string;
  power_status: string;
  server_status: string;
  v6_main_ip: string;
  v6_network: string;
  hostname: string;
  label: string;
  tag: string;
}

interface VultrCreateResponse {
  instance: VultrInstance;
}

interface VultrError {
  error: string;
  status: number;
}

export class VultrProvider extends VPSProviderBase {
  constructor(apiKey: string, timeout: number = 30000) {
    super({
      apiKey,
      baseUrl: 'https://api.vultr.com/v2',
      timeout,
    });
  }

  async createServer(request: CreateServerRequest): Promise<CreateServerResponse> {
    const url = `${this.config.baseUrl}/instances`;

    const body = {
      plan: request.plan,
      region: request.region,
      os_id: parseInt(request.osImage, 10),
      label: request.label || `server-${Date.now()}`,
      hostname: request.label || `server-${Date.now()}`,
      tag: request.tags?.[0] || '',
      sshkey_id: request.sshKeys || [],
      enable_ipv6: true,
      backups: 'disabled',
      ddos_protection: false,
    };

    try {
      const response = await this.fetchWithRetry(url, {
        method: 'POST',
        headers: {
          Authorization: `Bearer ${this.config.apiKey}`,
          'Content-Type': 'application/json',
        },
        body: JSON.stringify(body),
      });

      if (!response.ok) {
        const error = (await response.json()) as VultrError;
        return {
          success: false,
          error: {
            code: `VULTR_${response.status}`,
            message: error.error || 'Unknown error',
          },
        };
      }

      const data = (await response.json()) as VultrCreateResponse;
      const instance = data.instance;

      return {
        success: true,
        instanceId: instance.id,
        ipv4: instance.main_ip !== '0.0.0.0' ? instance.main_ip : undefined,
        ipv6: instance.v6_main_ip || undefined,
        status: instance.status,
      };
    } catch (error) {
      return {
        success: false,
        error: {
          code: 'VULTR_NETWORK_ERROR',
          message: error instanceof Error ? error.message : 'Network error',
        },
      };
    }
  }

  async deleteServer(instanceId: string): Promise<{ success: boolean; error?: string }> {
    const url = `${this.config.baseUrl}/instances/${instanceId}`;

    try {
      const response = await this.fetchWithRetry(url, {
        method: 'DELETE',
        headers: {
          Authorization: `Bearer ${this.config.apiKey}`,
        },
      });

      // Vultr returns 204 No Content on success
      if (response.status === 204 || response.ok) {
        return { success: true };
      }

      const error = (await response.json()) as VultrError;
      return {
        success: false,
        error: error.error || 'Failed to delete instance',
      };
    } catch (error) {
      return {
        success: false,
        error: error instanceof Error ? error.message : 'Network error',
      };
    }
  }

  async getServerStatus(
    instanceId: string
  ): Promise<{ status: string; ipv4?: string; ipv6?: string }> {
    const url = `${this.config.baseUrl}/instances/${instanceId}`;

    try {
      const response = await this.fetchWithRetry(url, {
        method: 'GET',
        headers: {
          Authorization: `Bearer ${this.config.apiKey}`,
        },
      });

      if (!response.ok) {
        return { status: 'unknown' };
      }

      const data = (await response.json()) as { instance: VultrInstance };
      return {
        status: data.instance.status,
        ipv4: data.instance.main_ip !== '0.0.0.0' ? data.instance.main_ip : undefined,
        ipv6: data.instance.v6_main_ip || undefined,
      };
    } catch {
      return { status: 'unknown' };
    }
  }

  getOsImageId(osImage: string): string {
    return OS_IMAGE_MAP.vultr[osImage as keyof typeof OS_IMAGE_MAP.vultr] || '2284'; // Default Ubuntu 22.04
  }

  /**
   * Wait for server to be ready (IP assigned)
   * Vultr servers may take a minute to get IP addresses
   */
  async waitForReady(
    instanceId: string,
    maxWaitMs: number = 120000
  ): Promise<{ ready: boolean; ipv4?: string; ipv6?: string }> {
    const startTime = Date.now();
    const pollInterval = 5000;

    while (Date.now() - startTime < maxWaitMs) {
      const status = await this.getServerStatus(instanceId);

      if (status.status === 'active' && status.ipv4) {
        return { ready: true, ipv4: status.ipv4, ipv6: status.ipv6 };
      }

      await this.sleep(pollInterval);
    }

    return { ready: false };
  }
}
