<?php

namespace App\Console\Commands;

use App\Components\Functions;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\Storage;

class TestMinioUpload extends Command
{
    protected $signature = 'minio:test-upload {--path= : Custom object path inside the bucket} {--delete : Delete the object after the test} {--public-check : Check public URL with a HEAD request}';

    protected $description = 'Upload a small test file to the configured MinIO S3 disk';

    public function handle()
    {
        $disk = 's3';
        $diskConfig = config('filesystems.disks.' . $disk);
        $path = $this->option('path') ?: 'healthcheck/itro-local-upload-' . date('Ymd-His') . '-' . uniqid() . '.txt';
        $path = ltrim($path, '/');
        $payload = 'itro.vn MinIO upload test' . PHP_EOL
            . 'Time: ' . date('c') . PHP_EOL
            . 'Path: ' . $path . PHP_EOL;

        $this->line('Disk: ' . $disk);
        $this->line('Endpoint: ' . array_get($diskConfig, 'endpoint'));
        $this->line('Bucket: ' . array_get($diskConfig, 'bucket'));
        $this->line('Object: ' . $path);

        try {
            $uploaded = Storage::disk($disk)->put($path, $payload);

            if ($uploaded === false) {
                $this->error('Upload returned false.');

                return 1;
            }

            $storedPayload = Storage::disk($disk)->get($path);

            if ($storedPayload !== $payload) {
                $this->error('Uploaded file was read back, but the content did not match.');

                return 1;
            }

            $url = Functions::cloudFileUrl($path, $disk);

            $this->info('Upload OK.');
            $this->line('Public URL: ' . $url);

            if ($this->option('public-check')) {
                $this->checkPublicUrl($url);
            }

            if ($this->option('delete')) {
                Storage::disk($disk)->delete($path);
                $this->info('Deleted test object.');
            }

            return 0;
        } catch (\Throwable $e) {
            $this->error(get_class($e) . ': ' . $e->getMessage());

            return 1;
        }
    }

    private function checkPublicUrl($url)
    {
        if (!function_exists('curl_init')) {
            $this->warn('Cannot check public URL because curl is not available.');

            return;
        }

        $ch = curl_init($url);
        curl_setopt($ch, CURLOPT_NOBODY, true);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_TIMEOUT, 10);
        curl_exec($ch);

        $error = curl_error($ch);
        $statusCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
        curl_close($ch);

        if (!empty($error)) {
            $this->warn('Public URL check failed: ' . $error);

            return;
        }

        if ($statusCode >= 200 && $statusCode < 400) {
            $this->info('Public URL check OK. HTTP ' . $statusCode);

            return;
        }

        $this->warn('Public URL check returned HTTP ' . $statusCode);
    }
}
