<?php
declare(strict_types=1);

namespace FlysystemOffload\Filesystem;

use FlysystemOffload\Filesystem\Adapters\AzureBlobAdapter;
use FlysystemOffload\Filesystem\Adapters\DropboxAdapter;
use FlysystemOffload\Filesystem\Adapters\GoogleCloudAdapter;
use FlysystemOffload\Filesystem\Adapters\GoogleDriveAdapter;
use FlysystemOffload\Filesystem\Adapters\OneDriveAdapter;
use FlysystemOffload\Filesystem\Adapters\S3Adapter;
use FlysystemOffload\Filesystem\Adapters\SftpAdapter;
use FlysystemOffload\Filesystem\Adapters\WebdavAdapter;
use FlysystemOffload\Helpers\PathHelper;
use League\Flysystem\Filesystem;
use League\Flysystem\FilesystemOperator;
use League\Flysystem\Local\LocalFilesystemAdapter;
use WP_Error;

class FilesystemFactory
{
    private array $settings;

    public function __construct(array $settings)
    {
        $this->settings = $settings;
    }

    public function make(): FilesystemOperator|WP_Error
    {
        $adapterKey = $this->settings['adapter'] ?? 'local';
        $config     = $this->settings['adapters'][$adapterKey] ?? [];

        $adapter = $this->resolveAdapter($adapterKey);

        if ($adapter instanceof WP_Error) {
            return $adapter;
        }

        $validation = $adapter->validate($config);
        if ($validation instanceof WP_Error) {
            return $validation;
        }

        $flyAdapter = $adapter->create($config);
        if ($flyAdapter instanceof WP_Error) {
            return $flyAdapter;
        }

        return new Filesystem($flyAdapter);
    }

    public function resolvePublicBaseUrl(string $adapterKey, array $settings): string
    {
        $adapter = $this->resolveAdapter($adapterKey);

        if ($adapter instanceof WP_Error) {
            return content_url('/uploads');
        }

        $baseUrl = $adapter->publicBaseUrl($settings);

        return untrailingslashit($baseUrl);
    }

    private function resolveAdapter(string $adapterKey): AdapterInterface|WP_Error
    {
        return match ($adapterKey) {
            's3'          => new S3Adapter(),
            'sftp'        => new SftpAdapter(),
            'gcs'         => new GoogleCloudAdapter(),
            'azure'       => new AzureBlobAdapter(),
            'webdav'      => new WebdavAdapter(),
            'googledrive' => new GoogleDriveAdapter(), // stub (dev)
            'onedrive'    => new OneDriveAdapter(),    // stub (dev)
            'dropbox'     => new DropboxAdapter(),     // stub (dev)
            default       => new class implements AdapterInterface {
                public function create(array $settings)
                {
                    $root = WP_CONTENT_DIR . '/flysystem-uploads';

                    return new LocalFilesystemAdapter($root);
                }

                public function publicBaseUrl(array $settings): string
                {
                    return content_url('/flysystem-uploads');
                }

                public function validate(array $settings)
                {
                    wp_mkdir_p(WP_CONTENT_DIR . '/flysystem-uploads');

                    return true;
                }
            },
        };
    }
}
