<?php

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

/**
 * Let a discount be scoped to members or to non-members.
 *
 * Until now the only thing the tier decided was which base price was read.
 * A club that wanted "10% off, members only" had no way to say it: the closest
 * rule type, membership_duration, is tenure in months, which is a different
 * question and matches non-members who have simply been around a while.
 *
 * This only widens a CHECK constraint. No existing row changes value, and the
 * new value is unreachable until a rule is authored with it.
 */
return new class extends Migration
{
    private const CONSTRAINT = 'pricing_rules_rule_type_check';

    private const TYPES = [
        'age', 'membership_duration', 'membership_type', 'family_size',
        'sibling_order', 'classification', 'enrollment_timing',
        'enrollment_volume', 'seasonal', 'gender', 'branch', 'day_time',
        'loyalty', 'custom',
    ];

    public function up(): void
    {
        if (! Schema::hasTable('pricing_rules')) {
            return;
        }

        $values = "'" . implode("', '", self::TYPES) . "'";

        // Dropped by name and rebuilt rather than altered — Postgres has no
        // ALTER CONSTRAINT for a CHECK. IF EXISTS so this is safe on a database
        // that somehow never got the original.
        DB::statement('ALTER TABLE pricing_rules DROP CONSTRAINT IF EXISTS ' . self::CONSTRAINT);
        DB::statement(
            'ALTER TABLE pricing_rules ADD CONSTRAINT ' . self::CONSTRAINT
            . " CHECK (rule_type IN ({$values}))"
        );
    }

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

        // Rules authored against the new value would violate the narrower
        // constraint, so they are retired first. Deactivating rather than
        // deleting: a discount someone applied is part of an invoice's history.
        DB::table('pricing_rules')
            ->where('rule_type', 'membership_type')
            ->update(['is_active' => false, 'rule_type' => 'custom']);

        $values = "'" . implode("', '", array_diff(self::TYPES, ['membership_type'])) . "'";

        DB::statement('ALTER TABLE pricing_rules DROP CONSTRAINT IF EXISTS ' . self::CONSTRAINT);
        DB::statement(
            'ALTER TABLE pricing_rules ADD CONSTRAINT ' . self::CONSTRAINT
            . " CHECK (rule_type IN ({$values}))"
        );
    }
};
