<?php

namespace routes;

use classes\economic;
use classes\router;
use classes\shelly;
use classes\slack;
use classes\virkdata;
use modules\shelly\helpers\shelly_device_switch;
use modules\shelly\helpers\shelly_request_body_get_states;
use modules\virkdata\helpers\virkdata_response;
use objects\departments_o;
use objects\orders_o;
use objects\product_options_o;
use objects\products_o;
use objects\users_o;
use traits\route_t;

class workerRoute
{
    use route_t;

    public function run(): void
    {
        $this->get('/worker/version', function () {
            global /** @var router $router */
            $response, $router;
            $response->success(['version' => redis->get('worker_target_version') ?? 'unknown'] );
        });
        $this->get('/worker/update-version', function () {
            global /** @var router $router */
            $response, $router;
            self::requirePermission('worker_update_version');
            self::requireParameters(['version']);
            $version = (string)self::getParameter('version');
            redis->set('worker_target_version', $version);
            $response->success(['message' => 'Version update functionality is not yet implemented.']);
        });
        $this->get('/worker/test', function () {
            global /** @var router $router */
            $response, $router;
            $response->error('This endpoint is disabled for security reasons.', 403);
            $department = (new departments_o())->select((int)6);
            $days = 7;
            // The time should be from 00:00:00 of the start date to 23:59:59 of the end date
            $date_end = date('Y-m-d 23:59:59', strtotime("-1 days")); // Yesterday (Sunday) at 23:59:59
            $date_start = date('Y-m-d 00:00:00', strtotime("-$days days")); // $days ago at 00:00:00
            $department->sendSlackInternalStatisticNotification($date_start, $date_end, [1,2,3,4,5,6,7]);
            $response->success(['message' => 'Test message sent to Slack (not really, this is a placeholder).' ]);
            exit;
            // Configuration
            $department_id = 6;
            /**
             * Weekly results for Roskilde
             *
             * Period: 29.01.2026 - 04.02.2026
             * Washes: 67
             * Fælg Flex: 55%
             * Spot Free: 22%
             * Special Sæbe: 11%
             * 10 min ekstra: 15%
             * Undervognsskyl: 44%
             * Voks: 66%
             */
             $max_addons = [];
             $sold_addons = [];
             $percentages = [];
             $department = (new departments_o())->select($department_id);
            echo "Testing addon sales calculation for department ID: $department_id from $date_start to $date_end\n";
            $tmp = "*Weekly results for {$department->name->value()}*\n";
            $tmp .= "Period: " . date('d.m.Y', strtotime($date_start)) . " - " . date('d.m.Y', strtotime($date_end)) . "\n";
            // Washes
            $wash_count = (new orders_o())->countWashesInDateRange($date_start, $date_end, $department_id);
            $tmp .= "Washes: $wash_count\n";
            // Get the percentage of addons sold out of max
            foreach ($product_ids as $product_id) {
                // Handle merged products
                if (is_array($product_id)) {
                    $addon_sold_count = 0;
                    $addon_max_count = 0;
                    foreach ($product_id as $pid) {
                        $pid = (int)$pid;
                        $addon_sold_count += (new product_options_o())->countSoldAddonsInDateRange($pid, $date_start, $date_end, $department_id);
                        $addon_max_count += (new product_options_o())->getMaxAddonsInDateRange($pid, $date_start, $date_end, $department_id);
                    }
                } else {
                    $pid = $product_id;
                    $addon_sold_count = (new product_options_o())->countSoldAddonsInDateRange($pid, $date_start, $date_end, $department_id);
                    $addon_max_count = (new product_options_o())->getMaxAddonsInDateRange($pid, $date_start, $date_end, $department_id);
                }
                // Prevent division by zero
                if ($addon_max_count === 0) {
                    $addon_percentage_sold = 0;
                } else {
                    $addon_percentage_sold = ($addon_sold_count / $addon_max_count) * 100;
                }
                $max_addons[is_array($product_id) ? implode('_', $product_id) : $product_id] = $addon_max_count;
                $sold_addons[is_array($product_id) ? implode('_', $product_id) : $product_id] = $addon_sold_count;
                $percentages[is_array($product_id) ? implode('_', $product_id) : $product_id] = number_format($addon_percentage_sold, 2);
            }
            foreach ($product_ids as $product_id) {
                if (is_array($product_id)) {
                    // Merged product names
                    $product_names = [];
                    foreach ($product_id as $pid) {
                        $product_names[] = (new products_o())->select($pid)->name->value();
                    }
                    // Switch to joined names
                    $product_name = match (true) {
                        in_array(23, $product_id) && in_array(24, $product_id) => 'Spot Free',
                        default => implode(' + ', $product_names),
                    };
                } else {
                    $product_name = (new products_o())->select($product_id)->name->value();
                }
                $tmp .= "{$product_name}: {$percentages[is_array($product_id) ? implode('_', $product_id) : $product_id]}%\n";
            }
            // Send test message to Slack
            $slack = new slack();
            $department = (new departments_o())->select($department_id);
            $slack->send_message($tmp);
            $response->success(['message' => 'Test message sent to Slack (not really, this is a placeholder).' ]);
        });
        $this->get('/worker/status', function () {
            global /** @var router $router */
            $response, $router;
            $response->success([
                'message' => 'Worker is running',
                'status' => 'OK',
                'time' => date('Y-m-d H:i:s'),
                'timezone' => date_default_timezone_get(),
                'host' => gethostname(),
                'version' => '1.0.1',
                'routes' => $router->countRoutes()
            ]);
        });
        $this->get('/worker/debug', function () {
           global /**  @var router $router */
            $response, $router;
            $response->error('This endpoint is disabled for security reasons.', 403);
            $shelly = new shelly();
            $shelly->requireModuleEnabled();
            $shelly->requireValidSecretKey();
            $parameters = new shelly_request_body_get_states();
            $parameters->ids = ['e4b323243f90'];
            $parameters->select = ['status'];
            $result = $shelly->sendPostRequest('/v2/devices/api/get', (array)$parameters);
            // Format the result
            $result = array_map(function ($device) {
                return (new shelly_device_switch())->populate($device);
            }, $result);
            //TODO: fetch statuses
            $response->success($result);
        });
        $this->get('/worker/debug/on', function () {
            global /**  @var router $router */
            $response, $router;
            $response->error('This endpoint is disabled for security reasons.', 403);
            $shelly = new shelly();
            $shelly->requireModuleEnabled();
            $shelly->requireValidSecretKey();
            $parameters = new shelly_request_body_get_states();
            $parameters->ids = ['e4b323243f90'];
            $parameters->select = ['status'];
            $result = $shelly->sendPostRequest('/v2/devices/api/get', (array)$parameters);
            // Wait 1 second
            sleep(1);
            // Format the result
            $result = array_map(function ($device) {
                return (new shelly_device_switch())->populate($device);
            }, $result);
            // Open the switch
            foreach ($result as $device) {
                $device->switch(true);
            }
            //TODO: fetch statuses
            $response->success($result);
        });
        $this->get('/worker/debug/off', function () {
            global /**  @var router $router */
            $response, $router;
            $response->error('This endpoint is disabled for security reasons.', 403);
            $shelly = new shelly();
            $shelly->requireModuleEnabled();
            $shelly->requireValidSecretKey();
            $parameters = new shelly_request_body_get_states();
            $parameters->ids = ['e4b323243f90'];
            $parameters->select = ['status'];
            $result = $shelly->sendPostRequest('/v2/devices/api/get', (array)$parameters);
            // Wait 1 second
            sleep(1);
            // Format the result
            $result = array_map(function ($device) {
                return (new shelly_device_switch())->populate($device);
            }, $result);
            // Open the switch
            foreach ($result as $device) {
                $device->switch(false);
            }
            //TODO: fetch statuses
            $response->success($result);
        });
        $this->get('/worker/licenseplates', function () {
            global /** @var router $router */
            $response, $db;
            $response->error('This endpoint is disabled for security reasons.', 403);
            $counted_plates = []; // Array to hold counted license plates
            // This is used to fetch all UNIQUE license plates from the database tables:
            // 'customer_vehicles' -> 'reg' column
            // 'orders' -> 'reg_1', 'reg_2', 'reg_3' columns
            // 'bookings' -> 'regNrTraekker', 'regNrTrailer' columns
            // 'plate_scans' -> 'plate' column
            $tables_and_columns = [
                'customer_vehicles' => ['reg'],
                'orders' => ['reg_1', 'reg_2', 'reg_3'],
                'bookings' => ['regNrTraekker', 'regNrTrailer'],
                'plate_scans' => ['plate'],
            ];
            foreach ($tables_and_columns as $table => $columns) {
                foreach ($columns as $column) {
                    $results = $db->query("SELECT DISTINCT $column FROM $table WHERE $column IS NOT NULL AND $column != ''");
                    foreach ($results as $row) {
                        $formatted_plate = $this->FORMAT_LICENSE_PLATE($row[$column]);
                        if ($formatted_plate !== '') {
                            if (!isset($counted_plates[$formatted_plate])) {
                                $counted_plates[$formatted_plate] = 0;
                            }
                            $counted_plates[$formatted_plate]++;
                        }
                    }
                }
            }
            $response->success(['counted_license_plates' => $counted_plates, 'total_unique_plates' => count($counted_plates)]);
        });
        $this->get('/economic/doesCustomerExist', function () {
           global $response;
           self::requirePermission( 'economic_does_customer_exist'); // TODO: Remove this
           self::requireParameters(['cvr']);
           $cvr = self::getParameter('cvr');
           // Check if the customer exists in E-conomic.
            if (!is_numeric($cvr)) {
                $response->error('Invalid CVR number', 400);
            }
            $economic = new economic();
            $results = $economic->customers->customers->search([
                'corporateIdentificationNumber' => (string)$cvr,
            ],[
                'skipPages' => 0,
                'pageSize' => 1000, // Since the limit is 1000, we need to set the page size to 1000.
            ])->collection;
            if (count($results) === 0) {
                $response->error('Customer not found', 404);
            }
           $response->success(['cvr' => $cvr, 'result' => $results], 200);
        });
        $this->get('/cvr/lookup', function () {
            global $response;
            self::requirePermission('cvr_lookup'); // TODO: Remove this
            self::requireParameters(['cvr']);
            $cvr = self::getParameter('cvr');
            if (!is_numeric($cvr)) {
                $response->error('Invalid CVR number', 400);
            }
            // Check if the result is cached
            if (!empty(redis->get('cvr_lookup_' . $cvr))) {
                $result = (new virkdata_response())->populate((array)json_decode(redis->get('cvr_lookup_' . $cvr)));
            } else {
                $virkdata = new virkdata();
                $result = $virkdata->getCompanyInformation($cvr, '', []);
                // Cache the result
                redis->set('cvr_lookup_' . $cvr, json_encode($result->asArray()));
                // Set the cache expiration time (3 days)
                redis->expire('cvr_lookup_' . $cvr, (60 * 60 * 24 * 4));
            }
            $response->success(['cvr' => $cvr, 'result' => (object)$result->asArray(), 'phone' => $result->phone, 'email' => $result->email], 200);
        });
    }

    protected function FORMAT_LICENSE_PLATE(string $plate): string
    {
        // Remove all non-alphanumeric characters
        $cleaned = preg_replace('/[^A-Za-z0-9]/', '', $plate);
        // Convert to uppercase
        return strtoupper($cleaned);
    }
}