<?php

namespace App\Services\Proxmox;

use App\Models\Host;

/**
 * Proxmox VE REST client, addressed per host over its wg_ip with a token.
 * A v1.0 uses it read-only (capacity + reachability); the automation token is
 * bootstrapped over SSH (pveum). Subsystem B extends it with VM lifecycle
 * methods (clone, cloud-init, guestExec …).
 */
interface ProxmoxClient
{
    /** Configure this client for a host (base URL from wg_ip, token from api_token_ref). */
    public function forHost(Host $host): static;

    /** @return array<int, array<string, mixed>> */
    public function listNodes(): array;

    /** @return array<string, mixed> */
    public function nodeStatus(string $node): array;

    /** @return array<int, array<string, mixed>> */
    public function nodeStorage(string $node): array;

    // --- VM lifecycle (Subsystem B) ---

    public function nextVmid(): int;

    /** Clone a template to a new VM; returns the task UPID. */
    public function cloneVm(string $node, int $templateVmid, int $newVmid, string $name): string;

    /**
     * The generic `PUT /nodes/{node}/qemu/{vmid}/config`, despite the name.
     *
     * It writes whatever parameters it is given; cloud-init keys are simply what
     * the first caller needed. `cores`, `memory` and the rest of a VM's ordinary
     * configuration go through here too — see ResizeVirtualMachine, which uses
     * it to apply a new plan's CPU and memory.
     *
     * @param  array<string, mixed>  $params
     */
    public function setCloudInit(string $node, int $vmid, array $params): void;

    public function resizeDisk(string $node, int $vmid, string $disk, string $size): void;

    /** Start a VM; returns the task UPID. */
    public function startVm(string $node, int $vmid): string;

    /**
     * ASK the guest to shut itself down, and return the task UPID.
     *
     * There is deliberately no counterpart that pulls the plug. Proxmox's
     * shutdown endpoint takes a `forceStop` flag that turns the request into a
     * power cut once the timeout runs out, and this interface does not expose
     * it: every guest we run is a Nextcloud, which is a database, and cutting
     * power to one mid-write to make a CPU change take effect trades a visible
     * inconvenience for a possible restore from backup. A guest that ignores
     * ACPI for the whole grace period is a guest that is doing something, and
     * the right answer there is a failed run an operator can look at — see
     * App\Provisioning\Steps\Customer\ShutDownVirtualMachine.
     *
     * $timeoutSeconds is how long Proxmox itself waits for the guest before it
     * gives the task up.
     */
    public function shutdownVm(string $node, int $vmid, int $timeoutSeconds): string;

    /**
     * Proxmox's own recorded history for a node — cpu, memused, memtotal, … per
     * sample, oldest first.
     *
     * $timeframe is one of hour|day|week|month|year; PVE keeps all five, so a
     * chart never has to be fed from a sampler of ours.
     *
     * @return array<int, array<string, mixed>>
     */
    public function nodeRrdData(string $node, string $timeframe = 'hour'): array;

    /** @return array<string, mixed> ['status' => 'running'|'stopped', …] */
    public function vmStatus(string $node, int $vmid): array;

    /** Whether a VM with this id already exists on the node. */
    public function vmExists(string $node, int $vmid): bool;

    /**
     * Whether that id is a real TEMPLATE (`template: 1`), not merely a VM.
     *
     * A separate question from vmExists(), and the one that actually matters
     * before a clone: an abandoned template build leaves an ordinary virtual
     * machine numbered 9000 behind, and everything that asked "does it exist"
     * called that fine — right up to the first paid order, which is where
     * clone_vm then failed.
     */
    public function isTemplate(string $node, int $vmid): bool;

    public function deleteVm(string $node, int $vmid): void;

    public function guestAgentPing(string $node, int $vmid): bool;

    /** @return array{exitcode: int, out-data: string} */
    public function guestExec(string $node, int $vmid, string $command): array;

    /** @return array{status: string, exitstatus?: string} */
    public function taskStatus(string $node, string $upid): array;

    /** @param array<int, array<string, mixed>> $rules */
    public function applyFirewall(string $node, int $vmid, array $rules): void;

    /**
     * Limit (or release) the VM's network interface.
     *
     * $mbytesPerSecond === null removes the limit. Proxmox expresses `rate` in
     * MB/s on the NIC definition, so the caller converts — this signature keeps
     * the unit visible instead of hiding a magic number.
     */
    public function setNetworkRate(string $node, int $vmid, ?float $mbytesPerSecond): void;

    /** Create a scheduled vzdump backup job for the VM; returns the job id. */
    public function createBackupJob(string $node, int $vmid, string $schedule): string;
}
