<?php

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

/**
 * Two CHECK vocabularies are wrong today, and both are live crashes.
 *
 * 1. notification_templates.channel and notification_logs.channel allow only
 *    in_app|email|sms, while NotificationChannel has whatsapp and push and
 *    PushNotificationService writes 'push'. Every push delivery log insert
 *    raises 23514 right now — and the catch block writes another failing
 *    insert. Push logging is 100% broken and this blocks the portal's push
 *    work outright.
 *
 * 2. guardians.relationship_type and guardian_participant.relationship_type
 *    carry different value lists, and NewRegistrationWizard validates one
 *    field ('brother','sister','guardian' allowed) and writes it to BOTH.
 *    A receptionist who picks أخ / أخت / وصي crashes registration on the
 *    guardians CHECK. Reconciling to the union of the two lists fixes the
 *    crash without invalidating a single existing row.
 *
 * Widening a CHECK is safe against a populated table: every row that passed
 * the old list passes the superset. DROP + ADD run inside the migration's own
 * transaction, so a failure leaves the original constraint in place.
 */
return new class extends Migration
{
    private const RELATIONSHIP_TYPES = [
        'father', 'mother', 'brother', 'sister', 'sibling',
        'uncle', 'aunt', 'grandfather', 'grandmother',
        'guardian', 'legal_guardian', 'other',
    ];

    private const NOTIFICATION_CHANNELS = ['in_app', 'email', 'sms', 'push', 'whatsapp'];

    public function up(): void
    {
        $this->widen('notification_templates', 'channel', 'notification_templates_channel_check', self::NOTIFICATION_CHANNELS);
        $this->widen('notification_logs', 'channel', 'notification_logs_channel_check', self::NOTIFICATION_CHANNELS);

        $this->widen('guardians', 'relationship_type', 'guardians_relationship_type_check', self::RELATIONSHIP_TYPES);
        $this->widen('guardian_participant', 'relationship_type', 'guardian_participant_relationship_type_check', self::RELATIONSHIP_TYPES);
    }

    private function widen(string $table, string $column, string $constraint, array $values): void
    {
        if (! Schema::hasTable($table) || ! Schema::hasColumn($table, $column)) {
            return;
        }

        if (DB::getDriverName() !== 'pgsql') {
            return;
        }

        $list = implode(', ', array_map(fn ($v) => "'{$v}'", $values));

        DB::statement("ALTER TABLE {$table} DROP CONSTRAINT IF EXISTS {$constraint}");
        DB::statement("ALTER TABLE {$table} ADD CONSTRAINT {$constraint} CHECK ({$column} IN ({$list}))");
    }

    public function down(): void
    {
        if (DB::getDriverName() !== 'pgsql') {
            return;
        }

        $this->widen('notification_templates', 'channel', 'notification_templates_channel_check', ['in_app', 'email', 'sms']);
        $this->widen('notification_logs', 'channel', 'notification_logs_channel_check', ['in_app', 'email', 'sms']);
        $this->widen('guardians', 'relationship_type', 'guardians_relationship_type_check', ['father', 'mother', 'grandfather', 'grandmother', 'uncle', 'aunt', 'sibling', 'legal_guardian', 'other']);
        $this->widen('guardian_participant', 'relationship_type', 'guardian_participant_relationship_type_check', ['father', 'mother', 'brother', 'sister', 'uncle', 'aunt', 'grandfather', 'grandmother', 'guardian', 'other']);
    }
};
