<?php

declare(strict_types=1);

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

/**
 * 销售订单明细：补齐行级定价快照与报价来源字段（与 SalesDocumentPricingService / 批量添加明细一致）。
 *
 * NOTE: 早期仅 dberp_sales_orders 表增加了 price_source_type，明细表遗漏会导致保存明细 SQL 失败。
 */
return new class extends Migration
{
    public function up(): void
    {
        if (! Schema::hasTable('dberp_sales_order_items')) {
            return;
        }

        Schema::table('dberp_sales_order_items', function (Blueprint $table): void {
            if (! Schema::hasColumn('dberp_sales_order_items', 'source_quote_item_id')) {
                $table->foreignId('source_quote_item_id')
                    ->nullable()
                    ->after('product_sku_id')
                    ->constrained('dberp_sales_quote_items')
                    ->nullOnDelete();
            }

            if (! Schema::hasColumn('dberp_sales_order_items', 'price_source_type')) {
                $table->string('price_source_type', 32)
                    ->nullable()
                    ->after('discount_amount')
                    ->comment('价格来源');
            }

            if (! Schema::hasColumn('dberp_sales_order_items', 'price_source_label')) {
                $table->string('price_source_label', 64)
                    ->nullable()
                    ->after('price_source_type')
                    ->comment('价格来源说明');
            }

            if (! Schema::hasColumn('dberp_sales_order_items', 'price_rule_id')) {
                $table->foreignId('price_rule_id')
                    ->nullable()
                    ->after('price_source_label')
                    ->constrained('dberp_customer_price_rules')
                    ->nullOnDelete();
            }

            if (! Schema::hasColumn('dberp_sales_order_items', 'matched_unit_price')) {
                $table->decimal('matched_unit_price', 18, 4)
                    ->nullable()
                    ->after('price_rule_id')
                    ->comment('命中规则价');
            }

            if (! Schema::hasColumn('dberp_sales_order_items', 'reference_unit_price')) {
                $table->decimal('reference_unit_price', 18, 4)
                    ->nullable()
                    ->after('matched_unit_price')
                    ->comment('默认销售价参考');
            }

            if (! Schema::hasColumn('dberp_sales_order_items', 'recent_transaction_unit_price')) {
                $table->decimal('recent_transaction_unit_price', 18, 4)
                    ->nullable()
                    ->after('reference_unit_price')
                    ->comment('最近成交价参考');
            }

            if (! Schema::hasColumn('dberp_sales_order_items', 'recent_transaction_date')) {
                $table->date('recent_transaction_date')
                    ->nullable()
                    ->after('recent_transaction_unit_price')
                    ->comment('最近成交日期');
            }
        });

        if (
            Schema::hasTable('dberp_sales_order_items')
            && Schema::hasColumn('dberp_sales_order_items', 'price_rule_id')
        ) {
            Schema::table('dberp_sales_order_items', function (Blueprint $table): void {
                if (! $this->indexExists('dberp_sales_order_items', 'idx_dsoi_price_rule')) {
                    $table->index(['price_rule_id'], 'idx_dsoi_price_rule');
                }

                if (
                    Schema::hasColumn('dberp_sales_order_items', 'source_quote_item_id')
                    && ! $this->indexExists('dberp_sales_order_items', 'idx_dsoi_source_quote_item')
                ) {
                    $table->index(['source_quote_item_id'], 'idx_dsoi_source_quote_item');
                }
            });
        }
    }

    private function indexExists(string $table, string $indexName): bool
    {
        $connection = Schema::getConnection();
        $driver = $connection->getDriverName();

        if ($driver === 'sqlite') {
            $rows = $connection->select('PRAGMA index_list(`'.$table.'`)');

            foreach ($rows as $row) {
                if (($row->name ?? null) === $indexName) {
                    return true;
                }
            }

            return false;
        }

        $database = $connection->getDatabaseName();

        $result = $connection->selectOne(
            'select count(*) as c from information_schema.statistics where table_schema = ? and table_name = ? and index_name = ?',
            [$database, $table, $indexName],
        );

        return isset($result->c) && (int) $result->c > 0;
    }

    public function down(): void
    {
        if (! Schema::hasTable('dberp_sales_order_items')) {
            return;
        }

        Schema::table('dberp_sales_order_items', function (Blueprint $table): void {
            if (Schema::hasColumn('dberp_sales_order_items', 'price_rule_id')) {
                $table->dropIndex('idx_dsoi_price_rule');
            }

            if (Schema::hasColumn('dberp_sales_order_items', 'source_quote_item_id')) {
                $table->dropIndex('idx_dsoi_source_quote_item');
            }
        });

        Schema::table('dberp_sales_order_items', function (Blueprint $table): void {
            if (Schema::hasColumn('dberp_sales_order_items', 'source_quote_item_id')) {
                $table->dropConstrainedForeignId('source_quote_item_id');
            }

            if (Schema::hasColumn('dberp_sales_order_items', 'price_rule_id')) {
                $table->dropConstrainedForeignId('price_rule_id');
            }

            $table->dropColumn(array_values(array_filter([
                Schema::hasColumn('dberp_sales_order_items', 'price_source_type') ? 'price_source_type' : null,
                Schema::hasColumn('dberp_sales_order_items', 'price_source_label') ? 'price_source_label' : null,
                Schema::hasColumn('dberp_sales_order_items', 'matched_unit_price') ? 'matched_unit_price' : null,
                Schema::hasColumn('dberp_sales_order_items', 'reference_unit_price') ? 'reference_unit_price' : null,
                Schema::hasColumn('dberp_sales_order_items', 'recent_transaction_unit_price') ? 'recent_transaction_unit_price' : null,
                Schema::hasColumn('dberp_sales_order_items', 'recent_transaction_date') ? 'recent_transaction_date' : null,
            ])));
        });
    }
};
