<?php

namespace App\Services;

use App\Models\Role;
use App\Models\User;
use App\Support\DatabaseSqlDumpExporter;
use Illuminate\Support\Facades\Artisan;
use RuntimeException;

class DatabaseResetService
{
    public function __construct(
        protected DatabaseSqlDumpExporter $exporter,
    ) {
    }

    public function resetForAdmin(User $admin): ?string
    {
        $adminSnapshot = [
            'name' => $admin->name,
            'email' => $admin->email,
            'password' => $admin->getAuthPassword(),
            'email_verified_at' => $admin->email_verified_at,
        ];

        $backupPath = $this->createBackupIfSupported();

        $this->runArtisan('migrate:fresh', [
            '--seed' => true,
            '--force' => true,
        ]);

        $this->restoreAdminCredentials($adminSnapshot);

        return $backupPath;
    }

    protected function createBackupIfSupported(): ?string
    {
        return $this->exporter->export(database_path('backups'));
    }

    protected function restoreAdminCredentials(array $snapshot): void
    {
        $adminRoleId = Role::query()->where('slug', 'admin')->value('id');

        $admin = User::query()->where('email', 'admin@example.com')->first() ?? new User();

        $admin->forceFill([
            'name' => $snapshot['name'],
            'email' => $snapshot['email'],
            'password' => $snapshot['password'],
            'email_verified_at' => $snapshot['email_verified_at'],
            'role' => 'admin',
            'role_id' => $adminRoleId,
            'remember_token' => null,
        ])->save();
    }

    protected function runArtisan(string $command, array $parameters = []): void
    {
        $exitCode = Artisan::call($command, $parameters);

        if ($exitCode !== 0) {
            $message = trim(Artisan::output());

            throw new RuntimeException(
                $message !== ''
                    ? $message
                    : sprintf('The [%s] command exited with code %d.', $command, $exitCode)
            );
        }
    }
}
