<?php

namespace routes;

use classes\authentication;
use classes\backup_store;
use classes\response;
use classes\router;
use objects\logs_o;
use Throwable;
use traits\route_t;

class moduleBackupsRoute
{
    use route_t;

    public function run(): void
    {
        global /** @var response $response */
        /** @var router $router */
        $router, $response;

        $this->get('/modules/backup/backups', function () {
            global $response;
            $this->requireClassicSuperuserPermission('modules_backup_list');
            try {
                $response->success(
                    (new backup_store())->listBackups(
                        (int)($this->fromQuery('limit') ?? 50),
                        (int)($this->fromQuery('offset') ?? 0)
                    )
                );
            } catch (Throwable $throwable) {
                $response->error(['message' => $throwable->getMessage()], 409);
            }
        }, [
            'modules_backup_list' => 'List backup records, components, and legacy metadata',
        ]);

        $this->post('/modules/backup/backups', function () {
            global $response;
            $this->requireClassicSuperuserPermission('modules_backup_create');
            $user_id = $this->actorUserId();
            try {
                $parameters = $this->getParametersAsArray();
                $result = (new backup_store())->enqueueCreateBackup(
                    $parameters['name'] ?? null,
                    $parameters['description'] ?? null,
                    $user_id,
                    'manual'
                );
                (new logs_o())->add('modules_backup', 'global', 1, $user_id ?? 0, 'MODULES_BACKUP', 'Queued backup: ' . $result['backup_uuid']);
                $response->success($result);
            } catch (Throwable $throwable) {
                $response->error(['message' => $throwable->getMessage()], 409);
            }
        }, [
            'modules_backup_create' => 'Queue a backup job',
        ]);

        $this->get('/modules/backup/jobs/{id}', function () {
            global $response;
            $this->requireClassicSuperuserPermission('modules_backup_list');
            $job_id = (int)$this->fromRoute('id');
            $job = (new backup_store())->getJob($job_id);
            if ($job === null) {
                $response->error('Backup job not found.', 404);
            }
            $response->success($job);
        }, [
            'modules_backup_list' => 'View backup job status',
        ]);

        $this->post('/modules/backup/backups/{backup_uuid}/verify', function () {
            global $response;
            $this->requireClassicSuperuserPermission('modules_backup_verify');
            try {
                $backup_uuid = (string)$this->fromRoute('backup_uuid');
                $result = (new backup_store())->enqueueVerifyBackup($backup_uuid, $this->actorUserId());
                (new logs_o())->add('modules_backup', 'global', 1, $this->actorUserId() ?? 0, 'MODULES_BACKUP_VERIFY', 'Queued backup verification: ' . $backup_uuid);
                $response->success($result);
            } catch (Throwable $throwable) {
                $response->error(['message' => $throwable->getMessage()], 409);
            }
        }, [
            'modules_backup_verify' => 'Verify a backup',
        ]);

        $this->post('/modules/backup/backups/{backup_uuid}/restore/preview', function () {
            global $response;
            $this->requireClassicSuperuserPermission('modules_backup_restore');
            try {
                $backup_uuid = (string)$this->fromRoute('backup_uuid');
                $result = (new backup_store())->previewRestore($backup_uuid, $this->actorUserId());
                (new logs_o())->add('modules_backup', 'global', 1, $this->actorUserId() ?? 0, 'MODULES_BACKUP_RESTORE_PREVIEW', 'Previewed backup restore: ' . $backup_uuid);
                $response->success($result);
            } catch (Throwable $throwable) {
                $response->error(['message' => $throwable->getMessage()], 409);
            }
        }, [
            'modules_backup_restore' => 'Preview production restore from a backup',
        ]);

        $this->post('/modules/backup/backups/{backup_uuid}/restore', function () {
            global $response;
            $this->requireClassicSuperuserPermission('modules_backup_restore');
            try {
                $parameters = $this->getParametersAsArray();
                $backup_uuid = (string)$this->fromRoute('backup_uuid');
                $result = (new backup_store())->enqueueRestore(
                    $backup_uuid,
                    (int)($parameters['preview_id'] ?? 0),
                    (string)($parameters['confirmation_phrase'] ?? ''),
                    (string)($parameters['reason'] ?? ''),
                    $this->actorUserId(),
                    [
                        'ip_address' => $_SERVER['REMOTE_ADDR'] ?? '',
                        'user_agent' => $_SERVER['HTTP_USER_AGENT'] ?? '',
                    ]
                );
                (new logs_o())->add('modules_backup', 'global', 1, $this->actorUserId() ?? 0, 'MODULES_BACKUP_RESTORE', 'Queued backup restore: ' . $backup_uuid);
                $response->success($result);
            } catch (Throwable $throwable) {
                $response->error(['message' => $throwable->getMessage()], 409);
            }
        }, [
            'modules_backup_restore' => 'Execute production restore from a backup',
        ]);

        $this->get('/modules/backup/restore-audit', function () {
            global $response;
            $this->requireClassicSuperuserPermission('modules_backup_restore');
            try {
                $response->success((new backup_store())->restoreAudit((int)($this->fromQuery('limit') ?? 50)));
            } catch (Throwable $throwable) {
                $response->error(['message' => $throwable->getMessage()], 409);
            }
        }, [
            'modules_backup_restore' => 'View backup restore audit log',
        ]);
    }

    private function requireClassicSuperuserPermission(string $permission): bool
    {
        global $response;

        if ((new authentication())->get_subuser() !== false) {
            $response->error('Subuser sessions cannot manage backup disaster recovery.', 403);
        }

        return $this->requirePermission($permission);
    }

    private function actorUserId(): ?int
    {
        try {
            $user = (new authentication())->get_user();
            return $user !== false && isset($user->id) ? (int)$user->id : null;
        } catch (Throwable) {
            return null;
        }
    }
}
