<?php

namespace Opencart\Extension\Alsendo\Handlers;

require_once(DIR_EXTENSION . 'alsendo/src/DTO/OrderShipmentSubmitDTO.php');
require_once(DIR_EXTENSION . 'alsendo/src/Helpers/RegionCurrency.php');

use Opencart\Extension\Alsendo\DTO\OrderShipmentSubmitDTO;
use Opencart\Extension\Alsendo\Helpers\RegionCurrency;
use Opencart\System\Engine\Registry;

class UpdateOrderDetailsFromSubmitHandler
{
    private Registry $registry;

    public function __construct(Registry $registry)
    {
        $this->registry = $registry;
    }

    public function update(OrderShipmentSubmitDTO $dto, string $regionCode): void
    {
        $this->registry->load->model('extension/alsendo/module/alsendo_order_details');
        $this->registry->load->model('extension/alsendo/module/alsendo_order_details_sender');
        $this->registry->load->model('extension/alsendo/module/alsendo_order_details_shipping_address');
        $this->registry->load->model('extension/alsendo/module/alsendo_order_details_package_details');
        $this->registry->load->model('extension/alsendo/module/alsendo_order_details_package');
        $this->registry->load->model('extension/alsendo/module/alsendo_order_details_shipment');

        $orderDetails = $this->registry->model_extension_alsendo_module_alsendo_order_details->getOrderDetailsByOrderId($dto->orderId);
        if (!$orderDetails) {
            return;
        }

        if ($orderDetails->sender !== null) {
            $senderData = $this->mapSenderFromDto($dto, $regionCode);
            $this->registry->model_extension_alsendo_module_alsendo_order_details_sender->updateSender($orderDetails->sender->id, $senderData);
        }

        if ($orderDetails->shippingAddress !== null) {
            $shippingData = $this->mapShippingAddressFromDto($dto, $regionCode);
            $this->registry->model_extension_alsendo_module_alsendo_order_details_shipping_address->updateShippingAddress($orderDetails->shippingAddress->id, $shippingData);
        }

        if ($orderDetails->packageDetails !== null) {
            $codValue = $dto->packageCod ? $dto->packageCod->toFloat() : null;
            if ($regionCode === 'czechia' && $codValue !== null && $codValue > 0) {
                $codValue = ceil($codValue);
            }
            $packageData = [
                'package_content' => $dto->packageContent,
                'cod_value' => $codValue !== null ? (string)$codValue : null,
                'declared_value' => $dto->packageDeclaredValue ? (string)$dto->packageDeclaredValue->toFloat() : null,
                'pickup_type' => $dto->selectedPickupType,
                'ship_via_pickup_point' => $dto->shipViaPickupPoint ? '1' : '0',
                'pickup_request' => $dto->pickupRequest ? '1' : '0',
            ];
            $this->registry->model_extension_alsendo_module_alsendo_order_details_package_details->updatePackageDetails($orderDetails->packageDetails->id, $packageData);

            $this->registry->model_extension_alsendo_module_alsendo_order_details_package->deleteByPackageDetailsId($orderDetails->packageDetails->id);
            foreach ($dto->packages as $pkg) {
                $pkgData = $pkg->toArray();
                $pkgData['template_id'] = $pkgData['package_template_id'] ?? null;
                $this->registry->model_extension_alsendo_module_alsendo_order_details_package->insertPackage($orderDetails->packageDetails->id, $pkgData);
            }
        }

        if ($orderDetails->shipment !== null) {
            $shipmentData = [
                'preferred_pickup_date' => $dto->shipmentPreferredPickupDate ?? date('Y-m-d'),
                'preferred_pickup_hour_from' => $dto->shipmentPreferredPickupHourFrom,
                'preferred_pickup_hour_to' => $dto->shipmentPreferredPickupHourTo,
                'shipment_pickup_point_display' => $dto->shipmentPickupPoint
                    ? (isset($dto->shipmentPickupPoint['name']) ? htmlspecialchars($dto->shipmentPickupPoint['name'], ENT_QUOTES, 'UTF-8') : null)
                    : null,
                'shipment_pickup_point' => $dto->shipmentPickupPoint,

            ];

            if ($dto->shipmentSelectedService !== null) {
                $shipmentData['service_id'] = $dto->shipmentSelectedService;
            }

            $this->registry->model_extension_alsendo_module_alsendo_order_details_shipment->updateShipment($orderDetails->shipment->id, $shipmentData);
        }

        $this->registry->model_extension_alsendo_module_alsendo_order_details->updateUpdatedAt($orderDetails->id);
    }

    private function mapSenderFromDto(OrderShipmentSubmitDTO $dto, string $regionCode): array
    {
        $data = [
            'address_type' => $dto->senderAddressType,
            'company_name' => $dto->senderCompanyName,
            'full_name' => $dto->senderFullName,
            'street' => $dto->senderStreet,
            'house_number' => $dto->senderHouseNumber,
            'apartment_number' => $dto->senderApartmentNumber,
            'country' => $dto->senderCountry,
            'postal_code' => $dto->senderPostalCode,
            'city' => $dto->senderCity,
            'phone_number' => $dto->senderPhoneNumber,
            'email' => $dto->senderEmail,
            'bank_account_number' => $dto->senderBankAccountNumber,
            'bank_code' => $dto->senderBankCode,
            'additional_bank_account_number' => $dto->senderAdditionalBankAccountNumber,
            'external_id' => $dto->senderExternalId,
            'delivery_point' => $dto->shippingPickupPoint ?? null,
            'sender_template_id' => $dto->senderTemplateId,
        ];
        if ($regionCode === 'romania') {
            $data['block'] = $dto->senderBlock;
            $data['entrance'] = $dto->senderEntrance;
            $data['floor'] = $dto->senderFloor;
        }
        return $data;
    }

    private function mapShippingAddressFromDto(OrderShipmentSubmitDTO $dto, string $regionCode): array
    {
        $fullName = trim(($dto->shippingFirstName ?? '') . ' ' . ($dto->shippingLastName ?? ''));
        $data = [
            'address_type' => $dto->shippingAddressType,
            'company_name' => $dto->shippingCompanyName,
            'full_name' => $fullName,
            'country' => $dto->shippingCountry,
            'postal_code' => $dto->shippingPostalCode,
            'city' => $dto->shippingCity,
            'phone_number' => $dto->shippingPhoneNumber,
            'email' => $dto->shippingEmail,
        ];
        if ($regionCode === 'romania') {
            $data['street'] = $dto->shippingStreet ?? $dto->shippingAddressOne;
            $data['house_number'] = $dto->shippingNumber ?? '';
            $data['apartment_number'] = $dto->shippingApartment ?? $dto->shippingAddressTwo;
            $data['block'] = $dto->shippingBlock;
            $data['entrance'] = $dto->shippingEntrance;
            $data['floor'] = $dto->shippingFloor;
        } else {
            $data['street'] = $dto->shippingAddressOne;
            $data['house_number'] = $dto->shippingAddressTwo ?? '';
            $data['apartment_number'] = $dto->shippingAddressTwo;
        }
        return $data;
    }
}
