<?php

namespace routes;

use classes\authentication;
use classes\coolify_manager;
use Throwable;
use traits\route_t;

class superuserCoolifyRoute
{
    use route_t;

    public function run(): void
    {
        $this->get('/superuser/coolify', function () {
            global $response;

            $this->requirePermission('superuser_coolify_view');
            $response->success((new coolify_manager())->summary());
        }, [
            'superuser_coolify_view' => 'View Coolify-managed replicated infrastructure targets',
        ]);

        $this->get('/superuser/coolify/load-balancer', function () {
            global $response;

            $this->requirePermission('superuser_coolify_view');
            $response->success((new coolify_manager())->loadBalancerSummary());
        }, [
            'superuser_coolify_view' => 'View the Coolify public gateway Load Balancer state',
        ]);

        $this->post('/superuser/coolify/load-balancer/reconcile', function () {
            global $response;

            $this->requirePermission('superuser_coolify_manage');
            try {
                $parameters = $this->getParametersAsArray();
                $dryRun = array_key_exists('dry_run', $parameters)
                    ? filter_var($parameters['dry_run'], FILTER_VALIDATE_BOOLEAN)
                    : !filter_var($parameters['enforce'] ?? false, FILTER_VALIDATE_BOOLEAN);
                $result = (new coolify_manager())->reconcileLoadBalancer($dryRun, $this->actorUserId());
                if (($result['ok'] ?? false) !== true) {
                    $response->error($result, 409);
                }
                $response->success($result);
            } catch (Throwable $throwable) {
                $response->error(['message' => $throwable->getMessage()], 409);
            }
        }, [
            'superuser_coolify_manage' => 'Reconcile Hetzner Load Balancer targets and services for the Coolify gateway',
        ]);

        $this->post('/superuser/coolify/load-balancer/routes/deploy', function () {
            global $response;

            $this->requirePermission('superuser_coolify_manage');
            try {
                $parameters = $this->getParametersAsArray();
                $dryRun = array_key_exists('dry_run', $parameters)
                    ? filter_var($parameters['dry_run'], FILTER_VALIDATE_BOOLEAN)
                    : !filter_var($parameters['enforce'] ?? false, FILTER_VALIDATE_BOOLEAN);
                $result = (new coolify_manager())->deployGatewayApplicationRoutes($dryRun, $this->actorUserId());
                if (($result['ok'] ?? false) !== true) {
                    $response->error($result, 409);
                }
                $response->success($result);
            } catch (Throwable $throwable) {
                $response->error(['message' => $throwable->getMessage()], 409);
            }
        }, [
            'superuser_coolify_manage' => 'Deploy the Coolify API application route for the public gateway host',
        ]);

        $this->post('/superuser/coolify/load-balancer/api/deploy', function () {
            global $response;

            $this->requirePermission('superuser_coolify_manage');
            try {
                $parameters = $this->getParametersAsArray();
                $dryRun = array_key_exists('dry_run', $parameters)
                    ? filter_var($parameters['dry_run'], FILTER_VALIDATE_BOOLEAN)
                    : !filter_var($parameters['enforce'] ?? false, FILTER_VALIDATE_BOOLEAN);
                $deployRoutes = array_key_exists('deploy_routes', $parameters)
                    ? filter_var($parameters['deploy_routes'], FILTER_VALIDATE_BOOLEAN)
                    : true;
                $result = (new coolify_manager())->deployGatewayApiCode($dryRun, $deployRoutes, $this->actorUserId());
                if (($result['ok'] ?? false) !== true) {
                    $response->error($result, 409);
                }
                $response->success($result);
            } catch (Throwable $throwable) {
                $response->error(['message' => $throwable->getMessage()], 409);
            }
        }, [
            'superuser_coolify_manage' => 'Deploy the latest Coolify API code for the public gateway host',
        ]);

        $this->get('/superuser/coolify/gateways', function () {
            global $response;

            $this->requirePermission('superuser_coolify_view');
            $response->success((new coolify_manager())->listLoadBalancerGateways());
        }, [
            'superuser_coolify_view' => 'List Coolify public gateway Load Balancer targets',
        ]);

        $this->post('/superuser/coolify/gateways', function () {
            global $response;

            $this->requirePermission('superuser_coolify_manage');
            try {
                $response->success((new coolify_manager())->saveLoadBalancerGateway(
                    $this->getParametersAsArray(),
                    $this->actorUserId()
                ), 201);
            } catch (Throwable $throwable) {
                $response->error(['message' => $throwable->getMessage()], 400);
            }
        }, [
            'superuser_coolify_manage' => 'Create or update Coolify public gateway Load Balancer targets',
        ]);

        $this->post('/superuser/coolify/gateways/{id}/test', function () {
            global $response;

            $this->requirePermission('superuser_coolify_manage');
            try {
                $response->success((new coolify_manager())->testLoadBalancerGateway(
                    $this->routeId(),
                    $this->actorUserId()
                ));
            } catch (Throwable $throwable) {
                $response->error(['message' => $throwable->getMessage()], 409);
            }
        }, [
            'superuser_coolify_manage' => 'Probe an individual Coolify public gateway target',
        ]);

        $this->post('/superuser/coolify/instances', function () {
            global $response;

            $this->requirePermission('superuser_coolify_manage');
            try {
                $response->success((new coolify_manager())->createInstance(
                    $this->getParametersAsArray(),
                    $this->actorUserId()
                ), 201);
            } catch (Throwable $throwable) {
                $response->error(['message' => $throwable->getMessage()], 400);
            }
        }, [
            'superuser_coolify_manage' => 'Create and update Coolify API connections',
        ]);

        $this->post('/superuser/coolify/instances/{id}/test', function () {
            global $response;

            $this->requirePermission('superuser_coolify_manage');
            $response->success((new coolify_manager())->testInstance($this->routeId(), $this->actorUserId()));
        }, [
            'superuser_coolify_manage' => 'Test Coolify API connectivity',
        ]);

        $this->get('/superuser/coolify/instances/{id}/placement', function () {
            global $response;

            $this->requirePermission('superuser_coolify_view');
            try {
                $response->success((new coolify_manager())->discoverInstancePlacement($this->routeId()));
            } catch (Throwable $throwable) {
                $response->error(['message' => $throwable->getMessage()], 502);
            }
        }, [
            'superuser_coolify_view' => 'Discover Coolify projects, environments, and servers for target placement',
        ]);

        $this->get('/superuser/coolify/targets', function () {
            global $response;

            $this->requirePermission('superuser_coolify_view');
            $kind = (string)($this->getParameter('kind') ?? '');
            $response->success((new coolify_manager())->listTargets($kind !== '' ? $kind : null));
        }, [
            'superuser_coolify_view' => 'List Coolify-managed replication targets',
        ]);

        $this->post('/superuser/coolify/targets', function () {
            global $response;

            $this->requirePermission('superuser_coolify_manage');
            try {
                $response->success((new coolify_manager())->createTarget(
                    $this->getParametersAsArray(),
                    $this->actorUserId()
                ), 201);
            } catch (Throwable $throwable) {
                $response->error(['message' => $throwable->getMessage()], 409);
            }
        }, [
            'superuser_coolify_manage' => 'Create Coolify-managed MariaDB, Redis, and MinIO replication targets',
        ]);

        $this->post('/superuser/coolify/targets/{id}/reconcile', function () {
            global $response;

            $this->requirePermission('superuser_coolify_reconcile');
            try {
                $result = (new coolify_manager())->reconcileTarget($this->routeId(), $this->actorUserId());
                if (($result['ok'] ?? false) !== true) {
                    $response->error($result, 409);
                }
                $response->success($result);
            } catch (Throwable $throwable) {
                $response->error(['message' => $throwable->getMessage()], 409);
            }
        }, [
            'superuser_coolify_reconcile' => 'Reconcile expected Coolify deployment state without primary downtime',
        ]);

        $this->post('/superuser/coolify/targets/{id}/deploy', function () {
            global $response;

            $this->requirePermission('superuser_coolify_reconcile');
            try {
                $result = (new coolify_manager())->deployTarget($this->routeId(), $this->actorUserId());
                if (($result['ok'] ?? false) !== true) {
                    $response->error($result, 409);
                }
                $response->success($result);
            } catch (Throwable $throwable) {
                $response->error(['message' => $throwable->getMessage()], 409);
            }
        }, [
            'superuser_coolify_reconcile' => 'Deploy and provision a passive Coolify-managed replication target',
        ]);

        $this->post('/superuser/coolify/targets/{id}/restart', function () {
            global $response;

            $this->requirePermission('superuser_coolify_reconcile');
            try {
                $result = (new coolify_manager())->restartTarget($this->routeId(), $this->actorUserId());
                if (($result['ok'] ?? false) !== true) {
                    $response->error($result, 409);
                }
                $response->success($result);
            } catch (Throwable $throwable) {
                $response->error(['message' => $throwable->getMessage()], 409);
            }
        }, [
            'superuser_coolify_reconcile' => 'Restart a passive Coolify target without restarting the active primary',
        ]);

        $this->post('/superuser/coolify/targets/{id}/failover', function () {
            global $response;

            $this->requirePermission('superuser_coolify_failover');
            try {
                $response->success((new coolify_manager())->failoverTarget($this->routeId(), $this->actorUserId()));
            } catch (Throwable $throwable) {
                $response->error(['message' => $throwable->getMessage()], 409);
            }
        }, [
            'superuser_coolify_failover' => 'Promote a healthy Coolify-managed replica through the replication module',
        ]);

        $this->delete('/superuser/coolify/targets/{id}', function () {
            global $response;

            $this->requirePermission('superuser_coolify_manage');
            try {
                $response->success((new coolify_manager())->deleteTarget(
                    $this->routeId(),
                    $this->getParametersAsArray(),
                    $this->actorUserId()
                ));
            } catch (Throwable $throwable) {
                $response->error(['message' => $throwable->getMessage()], 409);
            }
        }, [
            'superuser_coolify_manage' => 'Delete Coolify target mappings with explicit destructive confirmation',
        ]);
    }

    private function routeId(): int
    {
        $id = (int)$this->fromRoute('id');
        $this->requireParameterIntPositive($id, 'id');
        return $id;
    }

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