<?php

namespace routes;

use classes\authentication;
use classes\selfserve;
use modules\selfserve\classes\selfserve_machine_signal;
use modules\selfserve\classes\selfserve_wash_flow;
use objects\department_lanes_o;
use objects\logs_o;
use objects\plate_scanners_o;
use traits\route_t;

class machineButtonPressRoute
{
    use route_t;

    public function run(): void
    {
        $handler = function () {
            global $response;

            self::requirePlateScannerAuth();
            $plate_scanner = (new authentication())->get_plate_scanner();
            if (!$plate_scanner) {
                $response->error('Invalid plate scanner session', 403);
            }

            $lane_id = $this->resolveLaneId($plate_scanner);
            $reg = self::isParametersSet(['reg']) ? selfserve::standardize_registration((string)self::getParameter('reg')) : null;
            $payload = $this->getParametersAsArray();
            unset($payload['token']);

            try {
                $summary = (new selfserve_wash_flow())->recordMachineStartWebhook($lane_id, $reg, $payload);
            } catch (\RuntimeException $e) {
                $response->error($e->getMessage(), 404);
            }

            (new logs_o())->add('relay', $plate_scanner->department_id->value(), 1, 0, 'TRIGGER_BUTTON_PRESS', 'Button was pressed on the machine with the plate scanner: ' . $plate_scanner->id . ' for lane ' . $lane_id);
            $response->success([
                'message' => 'Button press recorded.',
                'scanner' => $plate_scanner->name->value(),
                'lane_id' => $lane_id,
                'selfserve' => $summary,
            ], 201);
        };

        $this->get('/relay/button/press/post', $handler, [
            'add_button_press' => 'Add a button press'
        ]);

        $this->post('/relay/button/press/post', $handler, [
            'add_button_press' => 'Add a button press'
        ]);

        $shellyHandler = function () {
            global $response;

            self::requirePlateScannerAuth();
            $plate_scanner = (new authentication())->get_plate_scanner();
            if (!$plate_scanner) {
                $response->error('Invalid plate scanner session', 403);
            }

            $payload = $this->getParametersAsArray();
            unset($payload['token']);
            $lane_id = self::isParametersSet(['lane_id']) ? (int)self::getParameter('lane_id') : null;

            try {
                $result = (new selfserve_machine_signal())->recordCloudShellySignal(
                    (int)$plate_scanner->department_id->value(),
                    $lane_id,
                    $payload,
                    [
                        'scanner_id' => (int)$plate_scanner->id,
                        'scanner_name' => (string)$plate_scanner->name->value(),
                    ]
                );
            } catch (\Throwable $e) {
                $response->error($e->getMessage(), 400);
            }

            (new logs_o())->add(
                'relay',
                $plate_scanner->department_id->value(),
                1,
                0,
                'TRIGGER_MACHINE_ON_SIGNAL',
                'Shelly machine ON signal received from plate scanner: ' . $plate_scanner->id
            );
            $response->success([
                'message' => !empty($result['recorded']) ? 'Machine ON signal recorded.' : 'Shelly signal ignored.',
                'scanner' => $plate_scanner->name->value(),
                'lane_id' => $result['lane_id'] ?? $lane_id,
                'signal' => $result['signal'] ?? null,
                'selfserve' => $result['selfserve'] ?? null,
                'ignored' => $result['ignored'] ?? false,
                'reason' => $result['reason'] ?? null,
            ], !empty($result['recorded']) ? 201 : 202);
        };

        $this->get('/relay/machine/on/post', $shellyHandler, [
            'add_button_press' => 'Record a Shelly machine ON signal'
        ]);

        $this->post('/relay/machine/on/post', $shellyHandler, [
            'add_button_press' => 'Record a Shelly machine ON signal'
        ]);
    }

    private function resolveLaneId(plate_scanners_o $plateScanner): int
    {
        global $response;

        if (self::isParametersSet(['lane_id'])) {
            $lane = (new department_lanes_o())->select((int)self::getParameter('lane_id'));
            if (!$lane->exists()) {
                $response->error('Department lane not found', 404);
            }
            if ((int)$lane->department->value() !== (int)$plateScanner->department_id->value()) {
                $response->error('The lane does not belong to the plate scanner department', 403);
            }
            return (int)$lane->id;
        }

        if ($plateScanner->lane_id->value() !== null) {
            $lane = (new department_lanes_o())->select((int)$plateScanner->lane_id->value());
            if (!$lane->exists()) {
                $response->error('The default lane configured for the plate scanner no longer exists', 404);
            }
            if ((int)$lane->department->value() !== (int)$plateScanner->department_id->value()) {
                $response->error('The default lane does not belong to the plate scanner department', 403);
            }
            return (int)$lane->id;
        }

        $lanes = (new department_lanes_o())->getDepartmentLanes((int)$plateScanner->department_id->value());
        if (count($lanes) === 1) {
            return (int)$lanes[0]->id;
        }

        $response->error('lane_id is required when the department has multiple self-serve lanes', 400);
    }
}
