<?php

namespace Opencart\Admin\Model\Extension\Alsendo\Module;

require_once(DIR_EXTENSION . 'alsendo/src/DTO/Entity/OrderDetailsEntityFactoryInterface.php');
require_once(DIR_EXTENSION . 'alsendo/src/DTO/Entity/Apaczka/ApaczkaOrderDetailsEntityFactory.php');

use Opencart\Extension\Alsendo\DTO\Entity\AbstractOrderDetailsSenderEntity;
use Opencart\Extension\Alsendo\DTO\Entity\OrderDetailsEntityFactoryInterface;
use Opencart\Extension\Alsendo\DTO\Entity\Apaczka\ApaczkaOrderDetailsEntityFactory;
use Opencart\System\Engine\Model;
use Opencart\System\Engine\Registry;

class AlsendoOrderDetailsSender extends Model
{
    public function __construct(Registry $registry)
    {
        parent::__construct($registry);
    }

    public function populate(): void
    {
        $this->db->query("
            CREATE TABLE IF NOT EXISTS `" . DB_PREFIX . "alsendo_order_details_sender` (
                `id` INT(11) UNSIGNED NOT NULL AUTO_INCREMENT,
                `sender_template_id` int(11) DEFAULT NULL,
                `order_details_id` INT(11) UNSIGNED DEFAULT NULL,
                `external_id` VARCHAR(255) NULL DEFAULT NULL,
                `address_type` VARCHAR(255) NULL DEFAULT NULL,
                `full_name` VARCHAR(255) NULL DEFAULT NULL,
                `company_name` VARCHAR(255) NULL DEFAULT NULL,
                `email` VARCHAR(255) NULL DEFAULT NULL,
                `phone_number` VARCHAR(255) NULL DEFAULT NULL,
                `bank_account_number` VARCHAR(255) NULL DEFAULT NULL,
                `bank_code` VARCHAR(255) NULL DEFAULT NULL,
                `additional_bank_account_number` VARCHAR(255) NULL DEFAULT NULL,
                `country` VARCHAR(255) NULL DEFAULT NULL,
                `city` VARCHAR(255) NULL DEFAULT NULL,
                `postal_code` VARCHAR(255) NULL DEFAULT NULL,
                `street` VARCHAR(255) NULL DEFAULT NULL,
                `house_number` VARCHAR(255) NULL DEFAULT NULL,
                `block` VARCHAR(255) NULL DEFAULT NULL,
                `entrance` VARCHAR(255) NULL DEFAULT NULL,
                `floor` VARCHAR(255) NULL DEFAULT NULL,
                `apartment_number` VARCHAR(255) NULL DEFAULT NULL,
                `shipping_point` JSON NULL DEFAULT NULL,
                PRIMARY KEY (`id`),
                CONSTRAINT `fk_alsendo_order_details_sender_order_details`
                    FOREIGN KEY (`order_details_id`)
                    REFERENCES `" . DB_PREFIX . "alsendo_order_details` (`id`)
                    ON DELETE CASCADE,
                CONSTRAINT `fk_alsendo_order_details_sender_sender_template`
                    FOREIGN KEY (`sender_template_id`)
                    REFERENCES `" . DB_PREFIX . "alsendo_sender_address_templates` (`id`)
                    ON DELETE CASCADE
            ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
        ");
    }

    public function getSenderByOrderDetailsId(int $orderDetailsId, ?OrderDetailsEntityFactoryInterface $factory = null): ?AbstractOrderDetailsSenderEntity
    {
        $query = $this->db->query("
            SELECT *
            FROM `" . DB_PREFIX . "alsendo_order_details_sender`
            WHERE order_details_id = '" . (int)$orderDetailsId . "'
            LIMIT 1
        ");
        if (!$query->num_rows) {
            return null;
        }
        $factory = $factory ?? new ApaczkaOrderDetailsEntityFactory();
        return $factory->createSenderFromArray($query->row);
    }

    public function insertSender(int $orderDetailsId, array $data): void
    {
        $shippingPoint = array_key_exists('shipping_point', $data) ? (is_array($data['shipping_point']) ? json_encode($data['shipping_point']) : $data['shipping_point']) : null;
        $sqlVal = function($key) use ($data) {
            return array_key_exists($key, $data) ? ($data[$key] === null ? "NULL" : "'" . $this->db->escape($data[$key]) . "'") : "NULL";
        };
        $this->db->query("
            INSERT INTO `" . DB_PREFIX . "alsendo_order_details_sender`
            SET `order_details_id` = '" . (int)$orderDetailsId . "',
                `sender_template_id` = " . $sqlVal('sender_template_id') . ",
                `external_id` = " . $sqlVal('external_id') . ",
                `address_type` = " . $sqlVal('address_type') . ",
                `full_name` = " . $sqlVal('full_name') . ",
                `company_name` = " . $sqlVal('company_name') . ",
                `email` = " . $sqlVal('email') . ",
                `phone_number` = " . $sqlVal('phone_number') . ",
                `bank_account_number` = " . $sqlVal('bank_account_number') . ",
                `bank_code` = " . $sqlVal('bank_code') . ",
                `additional_bank_account_number` = " . $sqlVal('additional_bank_account_number') . ",
                `country` = " . $sqlVal('country') . ",
                `city` = " . $sqlVal('city') . ",
                `postal_code` = " . $sqlVal('postal_code') . ",
                `street` = " . $sqlVal('street') . ",
                `house_number` = " . $sqlVal('house_number') . ",
                `block` = " . $sqlVal('block') . ",
                `entrance` = " . $sqlVal('entrance') . ",
                `floor` = " . $sqlVal('floor') . ",
                `apartment_number` = " . $sqlVal('apartment_number') . ",
                `shipping_point` = " . ($shippingPoint !== null ? "'" . $this->db->escape($shippingPoint) . "'" : "NULL") . "
        ");
    }

    public function updateSender(int $senderId, array $data): void
    {
        $updates = [];

        if (array_key_exists('sender_template_id', $data)) {
            $updates[] = ($data['sender_template_id'] === null || $data['sender_template_id'] === '') ? "`sender_template_id` = NULL" : "`sender_template_id` = '" . (int)$data['sender_template_id'] . "'";
        }

        if (array_key_exists('external_id', $data)) {
            $updates[] = $data['external_id'] === null ? "`external_id` = NULL" : "`external_id` = '" . $this->db->escape($data['external_id']) . "'";
        }

        if (array_key_exists('address_type', $data)) {
            $updates[] = $data['address_type'] === null ? "`address_type` = NULL" : "`address_type` = '" . $this->db->escape($data['address_type']) . "'";
        }

        if (array_key_exists('full_name', $data)) {
            $updates[] = $data['full_name'] === null ? "`full_name` = NULL" : "`full_name` = '" . $this->db->escape($data['full_name']) . "'";
        }

        if (array_key_exists('company_name', $data)) {
            $updates[] = $data['company_name'] === null ? "`company_name` = NULL" : "`company_name` = '" . $this->db->escape($data['company_name']) . "'";
        }

        if (array_key_exists('email', $data)) {
            $updates[] = $data['email'] === null ? "`email` = NULL" : "`email` = '" . $this->db->escape($data['email']) . "'";
        }

        if (array_key_exists('phone_number', $data)) {
            $updates[] = $data['phone_number'] === null ? "`phone_number` = NULL" : "`phone_number` = '" . $this->db->escape($data['phone_number']) . "'";
        }

        if (array_key_exists('bank_account_number', $data)) {
            $updates[] = $data['bank_account_number'] === null ? "`bank_account_number` = NULL" : "`bank_account_number` = '" . $this->db->escape($data['bank_account_number']) . "'";
        }

        if (array_key_exists('bank_code', $data)) {
            $updates[] = $data['bank_code'] === null ? "`bank_code` = NULL" : "`bank_code` = '" . $this->db->escape($data['bank_code']) . "'";
        }

        if (array_key_exists('additional_bank_account_number', $data)) {
            $updates[] = $data['additional_bank_account_number'] === null ? "`additional_bank_account_number` = NULL" : "`additional_bank_account_number` = '" . $this->db->escape($data['additional_bank_account_number']) . "'";
        }

        if (array_key_exists('country', $data)) {
            $updates[] = $data['country'] === null ? "`country` = NULL" : "`country` = '" . $this->db->escape($data['country']) . "'";
        }

        if (array_key_exists('city', $data)) {
            $updates[] = $data['city'] === null ? "`city` = NULL" : "`city` = '" . $this->db->escape($data['city']) . "'";
        }

        if (array_key_exists('postal_code', $data)) {
            $updates[] = $data['postal_code'] === null ? "`postal_code` = NULL" : "`postal_code` = '" . $this->db->escape($data['postal_code']) . "'";
        }

        if (array_key_exists('street', $data)) {
            $updates[] = $data['street'] === null ? "`street` = NULL" : "`street` = '" . $this->db->escape($data['street']) . "'";
        }

        if (array_key_exists('house_number', $data)) {
            $updates[] = $data['house_number'] === null ? "`house_number` = NULL" : "`house_number` = '" . $this->db->escape($data['house_number']) . "'";
        }

        if (array_key_exists('block', $data)) {
            $updates[] = $data['block'] === null ? "`block` = NULL" : "`block` = '" . $this->db->escape($data['block']) . "'";
        }

        if (array_key_exists('entrance', $data)) {
            $updates[] = $data['entrance'] === null ? "`entrance` = NULL" : "`entrance` = '" . $this->db->escape($data['entrance']) . "'";
        }

        if (array_key_exists('floor', $data)) {
            $updates[] = $data['floor'] === null ? "`floor` = NULL" : "`floor` = '" . $this->db->escape($data['floor']) . "'";
        }

        if (array_key_exists('apartment_number', $data)) {
            $updates[] = $data['apartment_number'] === null ? "`apartment_number` = NULL" : "`apartment_number` = '" . $this->db->escape($data['apartment_number']) . "'";
        }

        if (array_key_exists('shipping_point', $data)) {
            $shippingPoint = $data['shipping_point'] === null ? null : (is_array($data['shipping_point']) ? json_encode($data['shipping_point'], JSON_UNESCAPED_UNICODE | JSON_HEX_TAG | JSON_HEX_APOS | JSON_HEX_AMP | JSON_HEX_QUOT) : $data['shipping_point']);
            $updates[] = "`shipping_point` = " . ($shippingPoint !== null && $shippingPoint !== '' ? "'" . $this->db->escape($shippingPoint) . "'" : "NULL");
        }

        if (!empty($updates)) {
            $this->db->query("
                UPDATE `" . DB_PREFIX . "alsendo_order_details_sender`
                SET " . implode(", ", $updates) . "
                WHERE `id` = '" . (int)$senderId . "'
            ");
        }
    }
}
