<?php
/**
 * Copyright since 2025 InPost S.A.
 *
 * For the full license information, please view the LICENSE file bundled with the module.
 *
 * @author InPost S.A.
 * @copyright since 2025 InPost S.A.
 * @license MIT
 */

declare(strict_types=1);

namespace InPost\International\Installer\Database;

use Doctrine\DBAL\Schema\Schema;
use Doctrine\DBAL\Schema\Table;

if (!defined('_PS_VERSION_')) {
    exit;
}

final class Version_0_1_0 extends AbstractMigration
{
    private const CARRIER_TABLE_NAME = 'inpost_intl_carrier';
    private const CHECKOUT_SESSION_TABLE_NAME = 'inpost_intl_checkout_session';
    private const PICKUP_ADDRESS_TABLE_NAME = 'inpost_intl_pickup_address';
    private const PICKUP_ORDER_TABLE_NAME = 'inpost_intl_pickup_order';
    private const PARCEL_TPL_TABLE_NAME = 'inpost_intl_parcel_template';
    private const SHIPMENT_TABLE_NAME = 'inpost_intl_shipment';

    public function getVersion(): string
    {
        return '0.1.0';
    }

    public function up(Schema $schema): void
    {
        $this->configureCarrierTable($this->createTable($schema, self::CARRIER_TABLE_NAME));
        $this->configureCheckoutSessionTable($this->createTable($schema, self::CHECKOUT_SESSION_TABLE_NAME));
        $this->configurePickupAddressTable($this->createTable($schema, self::PICKUP_ADDRESS_TABLE_NAME));
        $this->configurePickupOrderTable($this->createTable($schema, self::PICKUP_ORDER_TABLE_NAME));
        $this->configureParcelTemplateTable($this->createTable($schema, self::PARCEL_TPL_TABLE_NAME));
        $this->configureShipmentTable($this->createTable($schema, self::SHIPMENT_TABLE_NAME));
    }

    public function down(Schema $schema): void
    {
        $this->dropTable($schema, self::CARRIER_TABLE_NAME);
        $this->dropTable($schema, self::CHECKOUT_SESSION_TABLE_NAME);
        $this->dropTable($schema, self::PICKUP_ADDRESS_TABLE_NAME);
        $this->dropTable($schema, self::PARCEL_TPL_TABLE_NAME);
    }

    private function configureCarrierTable(Table $table): void
    {
        $this->addColumn($table, 'id_reference', 'integer')->setUnsigned(true);
        $this->addColumn($table, 'type', 'string')->setLength(32);
        $this->addColumn($table, 'countries', 'simple_array');

        $this->setPrimaryKey($table, ['id_reference']);
    }

    private function configureCheckoutSessionTable(Table $table): void
    {
        $this->addColumn($table, 'id_cart', 'integer')->setUnsigned(true);
        $this->addColumn($table, 'points', 'json');

        $this->setPrimaryKey($table, ['id_cart']);
        $table->addForeignKeyConstraint($this->prefixTableName('cart'), ['id_cart'], ['id_cart'], [
            'onDelete' => 'CASCADE',
        ]);
    }

    private function configurePickupAddressTable(Table $table): void
    {
        $this->addColumn($table, 'id', 'integer')->setAutoincrement(true);
        $this->addColumn($table, 'name', 'string')->setLength(64);
        $this->addColumn($table, 'first_name', 'string')->setLength(64);
        $this->addColumn($table, 'last_name', 'string')->setLength(64);
        $this->addColumn($table, 'email', 'string')->setLength(320);
        $this->addColumn($table, 'phone_prefix', 'string')->setLength(4);
        $this->addColumn($table, 'phone_number', 'string')->setLength(16);
        $this->addColumn($table, 'street', 'string')->setLength(128);
        $this->addColumn($table, 'house_number', 'string')->setLength(16);
        $this->addColumn($table, 'flat_number', 'string')->setLength(16)->setNotnull(false);
        $this->addColumn($table, 'postcode', 'string')->setLength(12);
        $this->addColumn($table, 'city', 'string')->setLength(64);
        $this->addColumn($table, 'country', 'string')->setLength(2);
        $this->addColumn($table, 'description', 'string')->setLength(255)->setNotnull(false);
        $this->addColumn($table, 'is_default', 'boolean')->setDefault(false);
        $this->addColumn($table, 'is_deleted', 'boolean')->setDefault(false);

        $this->setPrimaryKey($table, ['id']);
        $this->addIndex($table, ['is_default', 'is_deleted']);
    }

    private function configurePickupOrderTable(Table $table): void
    {
        $this->addColumn($table, 'id', 'integer')->setAutoincrement(true);
        $this->addColumn($table, 'pickup_address_id', 'integer');
        $this->addColumn($table, 'pickup_time_start', 'datetime_immutable');
        $this->addColumn($table, 'pickup_time_end', 'datetime_immutable');
        $this->addColumn($table, 'uuid', 'guid');
        $this->addColumn($table, 'tracking_number', 'string')->setLength(32);
        $this->addColumn($table, 'reference', 'json')->setNotnull(false);
        $this->addColumn($table, 'created_at', 'datetime_immutable');

        $this->setPrimaryKey($table, ['id']);
        $table->addForeignKeyConstraint($this->prefixTableName(self::PICKUP_ADDRESS_TABLE_NAME), ['pickup_address_id'], ['id'], [
            'onDelete' => 'RESTRICT',
        ]);
    }

    private function configureParcelTemplateTable(Table $table): void
    {
        $this->addColumn($table, 'id', 'integer')->setAutoincrement(true);
        $this->addColumn($table, 'name', 'string')->setLength(64);
        $this->addColumn($table, 'type', 'string')->setLength(16);
        $this->addColumn($table, 'length', 'float')->setUnsigned(true);
        $this->addColumn($table, 'width', 'float')->setUnsigned(true);
        $this->addColumn($table, 'height', 'float')->setUnsigned(true);
        $this->addColumn($table, 'length_unit', 'string')->setLength(3);
        $this->addColumn($table, 'weight', 'float')->setUnsigned(true);
        $this->addColumn($table, 'weight_unit', 'string')->setLength(3);
        $this->addColumn($table, 'is_default', 'boolean')->setDefault(false);

        $this->setPrimaryKey($table, ['id']);
    }

    private function configureShipmentTable(Table $table): void
    {
        $this->addColumn($table, 'id', 'integer')->setAutoincrement(true);
        $this->addColumn($table, 'id_order', 'integer')->setLength(10)->setUnsigned(true);
        $this->addColumn($table, 'is_sandbox', 'boolean');
        $this->addColumn($table, 'type', 'string')->setLength(32);
        $this->addColumn($table, 'uuid', 'guid');
        $this->addColumn($table, 'tracking_number', 'string')->setLength(32);
        $this->addColumn($table, 'status', 'string')->setLength(32);
        $this->addColumn($table, 'reference', 'json')->setNotnull(false);
        $this->addColumn($table, 'recipient_email', 'string')->setLength(320);
        $this->addColumn($table, 'recipient_phone_prefix', 'string')->setLength(4);
        $this->addColumn($table, 'recipient_phone_number', 'string')->setLength(16);
        $this->addColumn($table, 'parcel_type', 'string')->setLength(16);
        $this->addColumn($table, 'parcel_length', 'float')->setUnsigned(true);
        $this->addColumn($table, 'parcel_width', 'float')->setUnsigned(true);
        $this->addColumn($table, 'parcel_height', 'float')->setUnsigned(true);
        $this->addColumn($table, 'parcel_length_unit', 'string')->setLength(3);
        $this->addColumn($table, 'parcel_weight', 'float')->setUnsigned(true);
        $this->addColumn($table, 'parcel_weight_unit', 'string')->setLength(3);
        $this->addColumn($table, 'parcel_comment', 'string')->setLength(128)->setNotnull(false);
        $this->addColumn($table, 'insurance_amount', 'integer')->setNotnull(false);
        $this->addColumn($table, 'insurance_currency', 'string')->setLength(3)->setNotnull(false);
        $this->addColumn($table, 'pickup_address_id', 'integer')->setNotnull(false);
        $this->addColumn($table, 'pickup_order_id', 'integer')->setNotnull(false);
        $this->addColumn($table, 'created_at', 'datetime_immutable');
        $this->addColumn($table, 'updated_at', 'datetime_immutable');

        $this->setPrimaryKey($table, ['id']);
        $table->addForeignKeyConstraint($this->prefixTableName('orders'), ['id_order'], ['id_order'], [
            'onDelete' => 'CASCADE',
        ]);
        $table->addForeignKeyConstraint($this->prefixTableName(self::PICKUP_ADDRESS_TABLE_NAME), ['pickup_address_id'], ['id'], [
            'onDelete' => 'RESTRICT',
        ]);
        $table->addForeignKeyConstraint($this->prefixTableName(self::PICKUP_ORDER_TABLE_NAME), ['pickup_order_id'], ['id'], [
            'onDelete' => 'RESTRICT',
        ]);

        $this->addIndex($table, ['tracking_number', 'is_sandbox']); // TODO: for webhook search?
    }
}
