<?php
declare(strict_types=1);

use Celena\Core\Database\Blueprint;
use Celena\Core\Database\Connection;
use Celena\Core\Database\Schema;

/**
 * Клиентская база магазина и расширение заказов.
 *
 * shop_customers: единая запись на email — заводится автоматически при оформлении
 * заказа (CheckoutController) или вручную из админки. Накапливает агрегаты
 * (orders_count / total_spent / last_order_at), которые обновляются триггером
 * на уровне приложения после успешного создания/смены статуса заказа.
 *
 * shop_orders расширяется полями для полноценного заказа:
 *   shipping_method_id / shipping_method_title / shipping_cost
 *   payment_method_id  / payment_method_title  / payment_status
 *   subtotal / discount / tax / promo_code / customer_id / admin_note
 * + история изменений в shop_order_history (статусы, оплата, заметки).
 *
 * Миграция идемпотентна: каждая колонка/таблица проверяется перед созданием.
 */
return function (Schema $schema, Connection $conn): void {
    $driver = $conn->driver()->name();

    $hasColumn = function (string $table, string $column) use ($conn, $driver): bool {
        $tbl = $conn->table($table);
        if ($driver === 'pgsql') {
            $row = $conn->run(
                "SELECT 1 FROM information_schema.columns WHERE table_name = ? AND column_name = ? LIMIT 1",
                [$tbl, $column]
            )->fetch();
        } else {
            $row = $conn->run(
                "SELECT 1 FROM information_schema.columns WHERE table_schema = DATABASE() AND table_name = ? AND column_name = ? LIMIT 1",
                [$tbl, $column]
            )->fetch();
        }
        return $row !== false && $row !== null;
    };

    if (!$schema->hasTable('shop_customers')) {
        $schema->create('shop_customers', function (Blueprint $t) {
            $t->id();
            $t->bigInteger('user_id')->nullable();
            $t->string('email', 191);
            $t->string('name', 191);
            $t->string('phone', 32)->nullable();
            $t->text('address')->nullable();
            $t->string('city', 100)->nullable();
            $t->string('country', 100)->nullable();
            $t->string('zip', 20)->nullable();
            $t->text('note')->nullable();
            // Агрегаты — пересчитываются на уровне приложения
            $t->integer('orders_count')->default(0);
            $t->decimal('total_spent', 14, 2)->default(0);
            $t->datetime('last_order_at')->nullable();
            // VIP / маркетинг
            $t->boolean('is_vip')->default(false);
            $t->boolean('marketing_opt_in')->default(false);
            $t->datetime('created_at')->nullable();
            $t->datetime('updated_at')->nullable();
            $t->unique('email');
            $t->index('user_id');
            $t->index('phone');
        });
    }

    if (!$schema->hasTable('shop_order_history')) {
        $schema->create('shop_order_history', function (Blueprint $t) {
            $t->id();
            $t->bigInteger('order_id');
            $t->bigInteger('user_id')->nullable(); // кто внёс изменение (admin)
            // status_changed | payment_changed | note | created | item_changed
            $t->string('event', 32);
            $t->string('from_value', 100)->nullable();
            $t->string('to_value', 100)->nullable();
            $t->text('comment')->nullable();
            $t->datetime('created_at');
            $t->index('order_id');
        });
    }

    $tblO = $conn->table_q('shop_orders');
    // DATETIME → TIMESTAMP в PostgreSQL.
    $dt = $driver === 'pgsql' ? 'TIMESTAMP' : 'DATETIME';

    $addCol = function (string $name, string $type) use ($conn, $tblO, $hasColumn): void {
        if (!$hasColumn('shop_orders', $name)) {
            $col = $conn->quoteId($name);
            $conn->exec("ALTER TABLE $tblO ADD COLUMN $col $type");
        }
    };

    $addCol('customer_id',           'BIGINT NULL');
    $addCol('subtotal',              'DECIMAL(12,2) NOT NULL DEFAULT 0');
    $addCol('discount',              'DECIMAL(12,2) NOT NULL DEFAULT 0');
    $addCol('tax',                   'DECIMAL(12,2) NOT NULL DEFAULT 0');
    $addCol('shipping_cost',         'DECIMAL(12,2) NOT NULL DEFAULT 0');
    $addCol('shipping_method_id',    'BIGINT NULL');
    $addCol('shipping_method_title', 'VARCHAR(200) NULL');
    $addCol('payment_method_id',     'BIGINT NULL');
    $addCol('payment_method_title',  'VARCHAR(200) NULL');
    // pending | paid | refunded | cancelled
    $addCol('payment_status',        "VARCHAR(20) NOT NULL DEFAULT 'pending'");
    $addCol('promo_code',            'VARCHAR(64) NULL');
    $addCol('admin_note',            'TEXT NULL');
    $addCol('source',                "VARCHAR(20) NOT NULL DEFAULT 'web'"); // web | admin | phone | api
    $addCol('paid_at',               $dt . ' NULL');
    $addCol('shipped_at',            $dt . ' NULL');
    $addCol('delivered_at',          $dt . ' NULL');

    // Бэкфилл: subtotal = total, если не задан, чтобы старые заказы корректно отображались.
    try {
        $colSub = $conn->quoteId('subtotal');
        $colTotal = $conn->quoteId('total');
        $conn->exec("UPDATE $tblO SET $colSub = $colTotal WHERE $colSub = 0 AND $colTotal > 0");
    } catch (\Throwable) {
    }
};
