/**
 * Linode VPS Provider Implementation
 * API Docs: https://www.linode.com/docs/api/
 */

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

interface LinodeInstance {
  id: number;
  label: string;
  status: string;
  ipv4: string[];
  ipv6: string;
  region: string;
  type: string;
  created: string;
  updated: string;
}

interface LinodeError {
  errors: Array<{
    field?: string;
    reason: string;
  }>;
}

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

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

    const body = {
      type: request.plan,
      region: request.region,
      image: request.osImage,
      root_pass: request.rootPassword,
      label: request.label || `server-${Date.now()}`,
      tags: request.tags || [],
      authorized_keys: request.sshKeys || [],
      booted: true,
    };

    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 LinodeError;
        return {
          success: false,
          error: {
            code: `LINODE_${response.status}`,
            message: error.errors?.[0]?.reason || 'Unknown error',
          },
        };
      }

      const data = (await response.json()) as LinodeInstance;

      return {
        success: true,
        instanceId: String(data.id),
        ipv4: data.ipv4?.[0],
        ipv6: data.ipv6?.split('/')[0], // Remove CIDR notation
        status: data.status,
      };
    } catch (error) {
      return {
        success: false,
        error: {
          code: 'LINODE_NETWORK_ERROR',
          message: error instanceof Error ? error.message : 'Network error',
        },
      };
    }
  }

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

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

      if (!response.ok) {
        const error = (await response.json()) as LinodeError;
        return {
          success: false,
          error: error.errors?.[0]?.reason || 'Failed to delete instance',
        };
      }

      return { success: true };
    } 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}/linode/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 LinodeInstance;
      return {
        status: data.status,
        ipv4: data.ipv4?.[0],
        ipv6: data.ipv6?.split('/')[0],
      };
    } catch {
      return { status: 'unknown' };
    }
  }

  getOsImageId(osImage: string): string {
    return OS_IMAGE_MAP.linode[osImage as keyof typeof OS_IMAGE_MAP.linode] || 'linode/ubuntu22.04';
  }

  /**
   * Generate secure root password for Linode
   * Linode requires: 6-128 chars, uppercase, lowercase, numeric
   */
  generateRootPassword(): string {
    return this.generateSecurePassword(32);
  }
}
