<?php

namespace Opencart\Extension\Alsendo\Handlers;

require_once(DIR_EXTENSION . 'alsendo/src/DTO/Entity/AlsendoRegionEntity.php');
require_once(DIR_EXTENSION . 'alsendo/src/DTO/OrderShipmentSubmitDTO.php');
require_once(DIR_EXTENSION . 'alsendo/src/OrderDetails/CreateOrderDetailsFactory.php');
require_once(DIR_EXTENSION . 'alsendo/src/Handlers/UpdateOrderDetailsFromSubmitHandler.php');
require_once(DIR_EXTENSION . 'alsendo/src/Repositories/OrderPickupPointRepository.php');

use Opencart\Extension\Alsendo\DTO\Entity\AlsendoRegionEntity;
use Opencart\Extension\Alsendo\DTO\OrderShipmentSubmitDTO;
use Opencart\Extension\Alsendo\OrderDetails\CreateOrderDetailsFactory;
use Opencart\Extension\Alsendo\Handlers\UpdateOrderDetailsFromSubmitHandler;
use Opencart\Extension\Alsendo\Repositories\OrderPickupPointRepository;
use Opencart\System\Engine\Registry;

class OrderPreSubmitSaveHandler
{
    private Registry $registry;
    private object $db;
    private string $dbPrefix;
    private OrderPickupPointRepository $orderPickupPointRepository;

    public function __construct(Registry $registry, object $db)
    {
        $this->registry = $registry;
        $this->db = $db;
        $this->dbPrefix = defined('\DB_PREFIX') ? \DB_PREFIX : '';

        $this->orderPickupPointRepository = new OrderPickupPointRepository($this->db, $this->dbPrefix);
    }

    public function save(OrderShipmentSubmitDTO $dto, AlsendoRegionEntity $currentEntity): void
    {
        $orderId = $dto->orderId;
        
        if (!$orderId) {
            return;
        }

        $this->updateOpenCartOrder($dto);
        $this->updateOrderDetails($dto, $currentEntity);
        $this->updateOrderPickupPoint($dto);
    }

    private function updateOpenCartOrder(OrderShipmentSubmitDTO $dto): void
    {
        $orderId = $dto->orderId;
        
        $updateFields = [];
        
        if (!empty($dto->shippingCompanyName)) {
            $updateFields[] = "`shipping_company` = '" . $this->db->escape($dto->shippingCompanyName) . "'";
        }
        
        if (!empty($dto->shippingFirstName)) {
            $updateFields[] = "`shipping_firstname` = '" . $this->db->escape($dto->shippingFirstName) . "'";
        }
        
        if (!empty($dto->shippingLastName)) {
            $updateFields[] = "`shipping_lastname` = '" . $this->db->escape($dto->shippingLastName) . "'";
        }
        
        if (!empty($dto->shippingAddressOne)) {
            $updateFields[] = "`shipping_address_1` = '" . $this->db->escape($dto->shippingAddressOne) . "'";
        }
        
        if (!empty($dto->shippingAddressTwo)) {
            $updateFields[] = "`shipping_address_2` = '" . $this->db->escape($dto->shippingAddressTwo) . "'";
        }
        
        if (!empty($dto->shippingPostalCode)) {
            $updateFields[] = "`shipping_postcode` = '" . $this->db->escape($dto->shippingPostalCode) . "'";
        }
        
        if (!empty($dto->shippingCity)) {
            $updateFields[] = "`shipping_city` = '" . $this->db->escape($dto->shippingCity) . "'";
        }
        
        if (!empty($dto->shippingEmail)) {
            $updateFields[] = "`email` = '" . $this->db->escape($dto->shippingEmail) . "'";
        }

        if (!empty($dto->shippingPhoneNumber)) {
            $updateFields[] = "`telephone` = '" . $this->db->escape($dto->shippingPhoneNumber) . "'";
        }

        if (!empty($updateFields)) {
            $sql = "UPDATE `" . $this->dbPrefix . "order` SET " . implode(', ', $updateFields) . " WHERE `order_id` = '" . (int)$orderId . "'";
            $this->db->query($sql);
        }

        if (empty($dto->shippingCountry)) {
            return;
        }

        $countryTable = $this->dbPrefix . "country";
        $hasNameColumn = $this->columnExists($countryTable, 'name');

        // Required tweak for support for multiple versions
        if ($hasNameColumn) {
            $countryQuery = $this->db->query("SELECT `country_id`, `name` FROM `" . $countryTable . "` WHERE `iso_code_2` = '" . $this->db->escape($dto->shippingCountry) . "' LIMIT 1");

            if ($countryQuery->num_rows) {
                $countryName = $countryQuery->row['name'];
                $countryId = (int)$countryQuery->row['country_id'];
                $this->db->query("UPDATE `" . $this->dbPrefix . "order` SET `shipping_country` = '" . $this->db->escape($countryName) . "', `shipping_country_id` = '" . $countryId . "' WHERE `order_id` = '" . (int)$orderId . "'");
            }
        } else {
            $countryDescriptionTable = $this->dbPrefix . "country_description";
            if ($this->tableExists($countryDescriptionTable)) {
                $countryQuery = $this->db->query("SELECT `country_id` FROM `" . $countryTable . "` WHERE `iso_code_2` = '" . $this->db->escape($dto->shippingCountry) . "' LIMIT 1");
                if ($countryQuery->num_rows) {
                    $countryId = (int) $countryQuery->row['country_id'];
                    $descriptionQuery = $this->db->query("SELECT `name` FROM `" . $countryDescriptionTable . "` WHERE `country_id` = '" . $countryId . "' ORDER BY `language_id` ASC LIMIT 1");
                    if ($descriptionQuery->num_rows) {
                        $countryName = $descriptionQuery->row['name'];
                        $this->db->query("UPDATE `" . $this->dbPrefix . "order` SET `shipping_country` = '" . $this->db->escape($countryName) . "', `shipping_country_id` = '" . $countryId . "' WHERE `order_id` = '" . (int)$orderId . "'");
                    }
                }
            }
        }
    }

    private function updateOrderDetails(OrderShipmentSubmitDTO $dto, AlsendoRegionEntity $currentRegion): void
    {
        $orderId = $dto->orderId;
        $this->registry->get('load')->model('extension/alsendo/module/alsendo_order_details');
        $orderDetailsModel = $this->registry->get('model_extension_alsendo_module_alsendo_order_details');
        $existingOrderDetails = $orderDetailsModel->getOrderDetailsByOrderId($orderId);
        
        if (!$existingOrderDetails) {
            $factory = new CreateOrderDetailsFactory($this->registry);
            $createOrderDetails = $factory->getCreateOrderDetailsForRegion($currentRegion);
            $createOrderDetails->createIfNotExists($orderId, false, $currentRegion);
        }
        
        $updateHandler = new UpdateOrderDetailsFromSubmitHandler($this->registry);
        $updateHandler->update($dto, $currentRegion->code);
    }

    private function updateOrderPickupPoint(OrderShipmentSubmitDTO $dto): void
    {
        $orderId = $dto->orderId;
        
        if (!empty($dto->shippingPickupPoint)) {
            $pickupPointData = is_array($dto->shippingPickupPoint) ? 
                json_encode($dto->shippingPickupPoint) : 
                $dto->shippingPickupPoint;
                
            $this->db->query("
                INSERT INTO `" . $this->dbPrefix . "alsendo_order_pickup_points`
                    SET order_id = '" . (int)$orderId . "',
                        pickup_point = '" . $this->db->escape($pickupPointData) . "'
                ON DUPLICATE KEY UPDATE pickup_point = VALUES(pickup_point)
            ");
        }
    }

    private function columnExists(string $table, string $column): bool
    {
        $result = $this->db->query("SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = '" . $this->db->escape($table) . "' AND COLUMN_NAME = '" . $this->db->escape($column) . "' LIMIT 1");
        return $result->num_rows > 0;
    }

    private function tableExists(string $table): bool
    {
        $result = $this->db->query("SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = '" . $this->db->escape($table) . "' LIMIT 1");
        return $result->num_rows > 0;
    }
} 