import config from "../config.ts";
import axios from "axios";
import { VMManager, type VM } from "./base.ts";

const DO_TOKEN = config.DO_TOKEN;
const region = "sfo3";
const gatewayHost = config.DO_GATEWAY;
const sshKeys = config.DO_SSH_KEYS.split(",");

export class DigitalOcean extends VMManager {
  size = "s-2vcpu-2gb"; // s-1vcpu-1gb, s-1vcpu-2gb, s-2vcpu-2gb, s-2vcpu-4gb, c-2, s-4vcpu-8gb
  largeSize = "s-4vcpu-8gb";
  minRetries = 5;
  reuseVMs = true;
  id = "DO";
  imageId = config.DO_IMAGE;
  startVM = async (name: string) => {
    const response = await axios({
      method: "POST",
      url: `https://api.digitalocean.com/v2/droplets`,
      headers: {
        Authorization: "Bearer " + DO_TOKEN,
        "Content-Type": "application/json",
      },
      data: {
        name: name,
        region: region,
        size: this.isLarge ? this.largeSize : this.size,
        image: Number(this.imageId),
        ssh_keys: sshKeys,
        private_networking: true,
        // user_data: cloudInit(),
        tags: [this.getTag()],
      },
    });
    const id = response.data.droplet.id;
    return id;
  };

  terminateVM = async (id: string) => {
    const response = await axios({
      method: "DELETE",
      url: `https://api.digitalocean.com/v2/droplets/${id}`,
      headers: {
        Authorization: "Bearer " + DO_TOKEN,
        "Content-Type": "application/json",
      },
    });
  };

  rebootVM = async (id: string) => {
    // Reboot the VM
    const response2 = await axios({
      method: "POST",
      url: `https://api.digitalocean.com/v2/droplets/${id}/actions`,
      headers: {
        Authorization: "Bearer " + DO_TOKEN,
        "Content-Type": "application/json",
      },
      data: {
        type: "reboot",
      },
    });
    return;
  };

  reimageVM = async (id: string) => {
    // Rebuild the VM
    const response2 = await axios({
      method: "POST",
      url: `https://api.digitalocean.com/v2/droplets/${id}/actions`,
      headers: {
        Authorization: "Bearer " + DO_TOKEN,
        "Content-Type": "application/json",
      },
      data: {
        type: "rebuild",
        image: Number(this.imageId),
      },
    });
    return;
  };

  getVM = async (id: string) => {
    const response = await axios({
      method: "GET",
      url: `https://api.digitalocean.com/v2/droplets/${id}`,
      headers: {
        Authorization: "Bearer " + DO_TOKEN,
        "Content-Type": "application/json",
      },
    });
    let server = this.mapServerObject(response.data.droplet);
    return server;
  };

  listVMs = async (filter: string) => {
    // console.log(filter, tags);
    const response = await axios({
      method: "GET",
      url: `https://api.digitalocean.com/v2/droplets`,
      headers: {
        Authorization: "Bearer " + DO_TOKEN,
        "Content-Type": "application/json",
      },
      params: {
        // TODO need to update if over 100 results
        per_page: 100,
        tag_name: filter,
      },
    });
    return response.data.droplets.map(this.mapServerObject);
  };

  powerOn = async (_id: string) => {};

  attachToNetwork = async (_id: string) => {};

  updateSnapshot = async () => {
    return "";
  };

  mapServerObject = (server: any): VM => {
    // const ip = server.networks.v4.find(
    //   (network: any) => network.type === 'private',
    // )?.ip_address;
    const ip = server.networks.v4.find(
      (network: any) => network.type === "public",
    )?.ip_address;
    return {
      id: server.id?.toString(),
      // The gateway handles SSL termination and proxies to the private IP
      host: ip ? `${gatewayHost}/?ip=${ip}` : "",
      provider: this.id,
      large: this.isLarge,
      region: this.region,
    };
  };
}
