<?php
/**
 * Contract every storage destination implements.
 *
 * Adding a new destination:
 *   1. Implement this interface (see {@see \Backreload\Destinations\LocalDestination} for the simplest reference).
 *   2. Register the class with the manager:
 *
 *      add_filter( 'backreload_register_destinations', function ( array $types ): array {
 *          $types['my_provider'] = \My\Plugin\MyDestination::class;
 *          return $types;
 *      } );
 *
 *   3. (Optional) Provide a connection form schema by overriding {@see Destination::config_schema()}.
 *
 * @package Backreload\Destinations
 */

namespace Backreload\Destinations;

use Backreload\Models\DestinationRecord;

if ( ! defined( 'ABSPATH' ) ) { exit; }

interface Destination {

	/** Machine identifier, lowercase a-z + underscore. */
	public static function type(): string;

	/** Human-readable label. */
	public static function label(): string;

	/**
	 * Field schema for the connection form (used by REST + frontend).
	 *
	 * @return array<int,array{key:string,label:string,type:string,required?:bool,secret?:bool,help?:string,options?:array<int,string>,default?:mixed}>
	 */
	public static function config_schema(): array;

	/**
	 * Validate user-supplied config. Throw \Backreload\Destinations\ValidationException with field errors on failure.
	 *
	 * @param array<string,mixed> $config
	 * @return array<string,mixed>  Sanitized config to persist.
	 */
	public function validate( array $config ): array;

	/** Ping the remote and return true on success. */
	public function test( DestinationRecord $dest ): bool;

	/**
	 * Upload a local file to the destination. Returns the remote object key/path on success.
	 */
	public function upload( DestinationRecord $dest, string $local_path, string $remote_name ): string;

	/** Download a previously uploaded file. */
	public function download( DestinationRecord $dest, string $remote_name, string $local_path ): bool;

	/** Delete a file from the destination. */
	public function delete( DestinationRecord $dest, string $remote_name ): bool;

	/**
	 * @return array{used:float,quota:float}  Both in GB. quota=0 means unbounded/unknown.
	 */
	public function usage( DestinationRecord $dest ): array;

	/**
	 * Whether this destination type can be browsed for existing backups
	 * (via {@see list_backups()}). Cloud destinations whose APIs we haven't
	 * wired up for listing should return false. Used by the "Import from
	 * destination" UI to filter the picker — keeps the frontend in step with
	 * server capabilities without hard-coding a list there.
	 */
	public function is_browsable(): bool;

	/**
	 * List existing backups present in the destination as
	 * `[ { ext_id, has_manifest, manifest|null, parts: [ { name, size } ] } ]`.
	 * Default implementation on AbstractDestination returns `[]` — override on
	 * destination types whose API supports listing (Local, FTP, SFTP, S3 family).
	 *
	 * @return array<int,array{ext_id:string,has_manifest:bool,manifest:?array,parts:array<int,array{name:string,size:int}>}>
	 */
	public function list_backups( DestinationRecord $dest ): array;
}
