<?php

namespace App\Console\Commands;

use Illuminate\Console\Command;
use Illuminate\Support\Facades\Storage;

class BackupDatabase extends Command
{
    protected $signature = 'backup:database {--keep=14 : Number of daily backups to keep}';

    protected $description = 'Back up the database to storage/app/backups with rotation';

    public function handle(): int
    {
        $connection = config('database.default');
        $config = config("database.connections.{$connection}");
        $timestamp = now()->format('Y-m-d_His');

        Storage::disk('local')->makeDirectory('backups');
        $directory = storage_path('app/backups');

        if ($connection === 'sqlite') {
            $source = $config['database'];

            if (!is_file($source)) {
                $this->error("SQLite database not found at {$source}");
                return self::FAILURE;
            }

            $target = "{$directory}/backup_{$timestamp}.sqlite";
            copy($source, $target);
        } elseif ($connection === 'mysql') {
            $target = "{$directory}/backup_{$timestamp}.sql.gz";
            $command = sprintf(
                'mysqldump --host=%s --port=%s --user=%s --password=%s %s | gzip > %s',
                escapeshellarg($config['host']),
                escapeshellarg((string) $config['port']),
                escapeshellarg($config['username']),
                escapeshellarg($config['password']),
                escapeshellarg($config['database']),
                escapeshellarg($target)
            );

            exec($command, $output, $exitCode);

            if ($exitCode !== 0 || !is_file($target) || filesize($target) === 0) {
                $this->error('mysqldump failed. Check that mysqldump is available on this server.');
                return self::FAILURE;
            }
        } else {
            $this->error("Unsupported database driver: {$connection}");
            return self::FAILURE;
        }

        $this->rotate($directory, (int) $this->option('keep'));
        $this->info("Database backed up to {$target}");

        return self::SUCCESS;
    }

    private function rotate(string $directory, int $keep): void
    {
        $backups = glob("{$directory}/backup_*");
        rsort($backups);

        foreach (array_slice($backups, max(1, $keep)) as $old) {
            @unlink($old);
        }
    }
}
