<?php

namespace objects;

use classes\db;
use classes\object_property;
use classes\xlvask;
use Exception;
use helpers\xlvask_customer;
use helpers\xlvask_usage_log;
use helpers\xlvask_vehicle;
use traits\db_object_t;

class xlvask_usage_logs_o extends db
{
    use db_object_t;

    public object_property $WashId;
    public object_property $CustomerId;
    public object_property $Customer;
    public object_property $VatNumber;
    public object_property $Location;
    public object_property $Hall;
    public object_property $HallId;
    public object_property $StartTime;
    public object_property $FinishTime;
    public object_property $RegistrationNumber;
    public object_property $VehicleType;
    public object_property $IdentificationType;
    public object_property $IdentificationId;
    public object_property $Info;
    public object_property $Updated;
    public object_property $Prepaid;
    public object_property $FinishStatus;
    public object_property $CustomerGuid;
    public object_property $VehicleId;
    public object_property $WashItems;

    public function structure(): void
    {
        $this->setTable('xlvask_usage_logs');
    }

    /**
     * Add a new XL Vask customer
     * @param array $data The properties
     * @returns void
     * @throws Exception If the object was not created successfully
     */
    public function add(array $data): void
    {
        $tmp_id = self::add_object($data);
        $this->id = $tmp_id;
        self::getObjectProperties();
        self::objectChanged();
    }

    public function getObjectProperties(): void
    {
        $this->WashId = new object_property($this->table, $this->id, 'WashId', 'string', false);
        $this->CustomerId = new object_property($this->table, $this->id, 'CustomerId', 'string', false);
        $this->Customer = new object_property($this->table, $this->id, 'Customer', 'string', false);
        $this->VatNumber = new object_property($this->table, $this->id, 'VatNumber', 'string', false);
        $this->Location = new object_property($this->table, $this->id, 'Location', 'string', false);
        $this->Hall = new object_property($this->table, $this->id, 'Hall', 'string', false);
        $this->HallId = new object_property($this->table, $this->id, 'HallId', 'string', false);
        $this->StartTime = new object_property($this->table, $this->id, 'StartTime', 'string', false);
        $this->FinishTime = new object_property($this->table, $this->id, 'FinishTime', 'string', false);
        $this->RegistrationNumber = new object_property($this->table, $this->id, 'RegistrationNumber', 'string', false);
        $this->VehicleType = new object_property($this->table, $this->id, 'VehicleType', 'string', false);
        $this->IdentificationType = new object_property($this->table, $this->id, 'IdentificationType', 'string', false);
        $this->IdentificationId = new object_property($this->table, $this->id, 'IdentificationId', 'string', false);
        $this->Info = new object_property($this->table, $this->id, 'Info', 'string', false);
        $this->Updated = new object_property($this->table, $this->id, 'Updated', 'string', false);
        $this->Prepaid = new object_property($this->table, $this->id, 'Prepaid', 'string', false);
        $this->FinishStatus = new object_property($this->table, $this->id, 'FinishStatus', 'string', false);
        $this->CustomerGuid = new object_property($this->table, $this->id, 'CustomerGuid', 'string', false);
        $this->VehicleId = new object_property($this->table, $this->id, 'VehicleId', 'string', false);
        $this->WashItems = new object_property($this->table, $this->id, 'WashItems', 'string', false);
    }

    public function objectChanged(): void
    {
        //TODO: Add cache invalidation
    }

    /**
     * Import the usage logs from XL Vask
     * @param string $dateTimeModifier A date time modifier to use for the import, defaults to '-7 days'
     * @throws Exception If the objects were not successfully added.
     * @returns void
     */
    public function importUsageLogs(string $dateTimeModifier = '-7 days'): void
    {
        if (!empty($this->id)) {
            throw new Exception('To prevent issues, having a selected object is not allowed.');
        }
        $usage_logs = $this->getUsageLogsFromXLVask(
            date('Y-m-d\TH:i:s.000', strtotime($dateTimeModifier)) // Example: '2025-05-01T00:00:00.000'
        );
        /** @var string[] $known_usage_logIds The XL Vask usage logIds currently known */
        $known_usage_logIds = array_map(function ($log) {
            return $log['WashId'];
        },
            self::getFieldsWhere(
                ['WashId' => array_column($usage_logs, 'WashId')],
                ['WashId']
            ));
        /** The XL Vask usage logs without a matching WashId in the database */
        $new_usage_logs = array_filter($usage_logs, function ($log) use ($known_usage_logIds) {
            return !in_array($log->WashId, $known_usage_logIds);
        });
        unset($known_usage_logIds);
        unset($usage_logs);
        /** Adding the new usage logs */
        foreach ($new_usage_logs as $log) {
            if (!$log->isValid()) {
                echo $log->formattedDetails();
                throw new Exception('A usage log from XL Vask is not valid, have the structure changed?');
            }
        }
        // Actually save the usage log
        foreach ($new_usage_logs as $log) {
            /** @var xlvask_usage_log $log */
            $this->add($log->toArray());
        }
        unset($new_usage_logs);
    }

    /**
     * This function retrieves the usage logs from XL Vask
     * @param string $fromDate The date from which to retrieve the usage logs, in ISO 8601 format (e.g., '2025-05-01T00:00:00.000')
     * @returns xlvask_usage_log[]
     * @throws Exception
     */
    public function getUsageLogsFromXLVask(string $fromDate): array
    {
        // Validate the date format
        if (!preg_match('/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{3}$/', $fromDate)) {
            throw new Exception('Invalid date format. Expected format: YYYY-MM-DDTHH:MM:SS.SSS (e.g., 2025-05-01T00:00:00.000)');
        }
        // Set the memory limit to 512MB, as the import can be quite large
        ini_set('memory_limit', '512M');
        /** Get the vehicles from XL Vask */
        $xlvask = new xlvask();
        $vehicle_class = $xlvask->new($xlvask->helpers->xlvask_usage_log);
        /** @var xlvask_usage_log[] $vehicles */
        $vehicles = $vehicle_class->toObjects($xlvask->getUsageLog(
            $fromDate, // Example: '2025-05-01T00:00:00.000'
        ));
        return $vehicles;
    }
}