<?php

namespace Opencart\Catalog\Controller\Extension\Alsendo\Event;

require_once(DIR_EXTENSION . 'alsendo/src/DTO/Entity/LogEntity.php');
require_once(DIR_EXTENSION . 'alsendo/src/DTO/Entity/AlsendoRegionEntity.php');
require_once(DIR_EXTENSION . 'alsendo/src/Providers/FullOrderProvider.php');
require_once(DIR_EXTENSION . 'alsendo/src/Services/WrapperService.php');
require_once(DIR_EXTENSION . 'alsendo/src/Services/OrderShipmentPackageService.php');
require_once(DIR_EXTENSION . 'alsendo/src/Enums/OrderShipmentStatus.php');
require_once(DIR_EXTENSION . 'alsendo/src/Models/OrderShipment.php');
require_once(DIR_EXTENSION . 'alsendo/src/Models/WrapperResult.php');
require_once(DIR_EXTENSION . 'alsendo/src/Providers/AdditionalSettingsDataProvider.php');
require_once(DIR_EXTENSION . 'alsendo/src/Repositories/AdditionalSettingsRepository.php');
require_once(DIR_EXTENSION . 'alsendo/src/Repositories/ConfigRepository.php');
require_once(DIR_EXTENSION . 'alsendo/src/Repositories/ServicesRepository.php');
require_once(DIR_EXTENSION . 'alsendo/src/Repositories/OrderShipmentPackageRepository.php');
require_once(DIR_EXTENSION . 'alsendo/src/Repositories/OrderShipmentRepository.php');
require_once(DIR_EXTENSION . 'alsendo/src/Repositories/SenderAddressRepository.php');
require_once(DIR_EXTENSION . 'alsendo/src/Handlers/AlsendoShipmentStatusChangeHandler.php');

use Opencart\Extension\Alsendo\DTO\Entity\AlsendoRegionEntity;
use Opencart\Extension\Alsendo\DTO\Entity\LogEntity;
use Opencart\Extension\Alsendo\Enums\OrderShipmentStatus;
use Opencart\Extension\Alsendo\Handlers\AlsendoShipmentStatusChangeHandler;
use Opencart\Extension\Alsendo\Models\OrderShipment;
use Opencart\Extension\Alsendo\Providers\AdditionalSettingsDataProvider;
use Opencart\Extension\Alsendo\Providers\FullOrderProvider;
use Opencart\Extension\Alsendo\Repositories\AdditionalSettingsRepository;
use Opencart\Extension\Alsendo\Repositories\ConfigRepository;
use Opencart\Extension\Alsendo\Repositories\OrderShipmentPackageRepository;
use Opencart\Extension\Alsendo\Repositories\OrderShipmentRepository;
use Opencart\Extension\Alsendo\Repositories\SenderAddressRepository;
use Opencart\Extension\Alsendo\Repositories\ServicesRepository;
use Opencart\Extension\Alsendo\Services\OrderShipmentPackageService;
use Opencart\Extension\Alsendo\Services\WrapperService;
use Opencart\System\Engine\Registry;

class Shipment extends \Opencart\System\Engine\Controller
{
    private ConfigRepository $configRepository;
    private FullOrderProvider $fullOrderProvider;
    private WrapperService $wrapperService;
    private ServicesRepository $servicesRepository;
    private OrderShipmentRepository $orderShipmentRepository;
    private OrderShipmentPackageService $orderShipmentPackageService;
    private AlsendoShipmentStatusChangeHandler $alsendoShipmentStatusChangeHandler;
    private AdditionalSettingsRepository $additionalSettingsRepository;
    private AdditionalSettingsDataProvider $additionalSettingsDataProvider;
    private SenderAddressRepository $senderAddressRepository;

    public function __construct(Registry $registry)
    {
        parent::__construct($registry);

        $this->fullOrderProvider = new FullOrderProvider($registry, $this->db);
        $this->servicesRepository = new ServicesRepository($this->db, \DB_PREFIX);
        $this->configRepository = new ConfigRepository($this->db, \DB_PREFIX);
        $this->senderAddressRepository = new SenderAddressRepository($this->db, \DB_PREFIX);

        $this->additionalSettingsRepository = new AdditionalSettingsRepository($this->db, \DB_PREFIX);
        $this->additionalSettingsDataProvider = new AdditionalSettingsDataProvider($this->additionalSettingsRepository);

        $this->wrapperService = new WrapperService(
            $registry,
            DIR_EXTENSION . 'alsendo/',
            $this->servicesRepository,
            $this->additionalSettingsDataProvider,
            $this->senderAddressRepository,
        );

        $this->orderShipmentRepository = new OrderShipmentRepository($this->db, \DB_PREFIX);
        $this->orderShipmentPackageService = new OrderShipmentPackageService(
            new OrderShipmentPackageRepository($this->db, \DB_PREFIX)
        );

        $this->alsendoShipmentStatusChangeHandler = new AlsendoShipmentStatusChangeHandler($registry, $this->db);
    }

    public function triggerShipmentOnOrderStatusChange(string &$route, array &$args): void {
        $this->load->language('extension/alsendo/main');
        $orderId = (int)$args[0];
        $orderStatusId = (int)$args[1];

        $this->load->model('extension/alsendo/module/alsendo_shipment_status');
        $triggerableOrderStatusId = $this->model_extension_alsendo_module_alsendo_shipment_status->getShipmentTriggerStatusId();

        if (empty($triggerableOrderStatusId)) {
            return;
        }

        if ($orderStatusId === $triggerableOrderStatusId) {
            $config = $this->configRepository->getConfig();
            $fullOrderDTO = $this->fullOrderProvider->getByOrderId($orderId);
            $result = $this->wrapperService->sendOrder($config, $fullOrderDTO);

            $this->load->model('extension/alsendo/module/alsendo_region');
            /** @var AlsendoRegionEntity $currentRegion */
            $currentRegion = $this->model_extension_alsendo_module_alsendo_region->getCurrentRegion();

            if ($result->isSuccess()) {
                $createdAlsendoOrderShipmentData = $result->getData();

                if (!empty($createdAlsendoOrderShipmentData['id'])) {
                    $orderShipment = new OrderShipment(
                        $currentRegion->id,
                        null,
                        $orderId,
                        $createdAlsendoOrderShipmentData,
                        null,
                        null,
                        $createdAlsendoOrderShipmentData['id'],
                        OrderShipmentStatus::NEW
                    );
                    $orderShipmentId = $this->orderShipmentRepository->upsert($orderShipment);
                    $this->orderShipmentPackageService->createFromOrderShipmentSubmit($fullOrderDTO, $orderShipmentId);
                    $this->alsendoShipmentStatusChangeHandler->handle($orderShipment, true);
                }
            } else {
                $this->load->model('extension/alsendo/module/log');

                $log = new LogEntity();
                $log->entityType = 'order';
                $log->entityId = $orderId;
                $log->logType = 'error';
                $log->data = sprintf('%s: %s',
                    $this->language->get('text_error_while_attempting_to_create_shipment_by_order_status_change_trigger'),
                    $result->getError(),
                );

                $this->model_extension_alsendo_module_log->saveLog($log);
            }
        }
    }
}