<?php

declare(strict_types=1);

use Phinx\Migration\AbstractMigration;

final class TaskInc61803 extends AbstractMigration
{
    public function up(): void
    {
        $this->execute(<<<SQL
            CREATE TABLE IF NOT EXISTS log.bloqueio_proposta_status (
                id SERIAL NOT NULL,
                id_proposta INTEGER NOT NULL,
                CONSTRAINT pk_bloqueio_proposta_status PRIMARY KEY (id),
                CONSTRAINT un_bloqueio_proposta_status UNIQUE (id_proposta),
                CONSTRAINT fk_bloqueio_proposta_status FOREIGN KEY (id_proposta) REFERENCES seguro.propostas(id)
            )
            INHERITS (public.campos_default); 

            CREATE INDEX IF NOT EXISTS idx_bloqueio_proposta_status_id_proposta ON log.bloqueio_proposta_status (id_proposta);

            CREATE OR REPLACE FUNCTION seguro.fn_bloquear_if_exists_bloqueio_proposta_status() RETURNS trigger
                LANGUAGE plpgsql
            AS 
            $$
            DECLARE
            target integer;
            BEGIN
            -- Bloqueia insert na tabela propostas_status evitando que um status seja alterado enquanto a proposta está na fila para emissão
            IF EXISTS (
                SELECT 1
                FROM log.bloqueio_proposta_status
                WHERE id_proposta = NEW.id_proposta
            ) THEN
                RAISE EXCEPTION
                'A proposta % está na fila de emissão, aguarde até que o processo de emissão seja concluído', 
                NEW.id_proposta
                USING ERRCODE = '23503'; --foreign_key_violation
            END IF;

            RETURN NEW;
            END;
            $$;

            DROP TRIGGER IF EXISTS trg_bloquear_if_exists_bloqueio_proposta_status_on_insert ON seguro.propostas_status;
            DROP TRIGGER IF EXISTS trg_bloquear_if_exists_bloqueio_proposta_status_on_update ON seguro.propostas_status;

            CREATE TRIGGER trg_bloquear_if_exists_bloqueio_proposta_status_on_insert
            BEFORE INSERT ON seguro.propostas_status
            FOR EACH ROW
            WHEN (NEW.id_status IS DISTINCT FROM 8)
            EXECUTE FUNCTION seguro.fn_bloquear_if_exists_bloqueio_proposta_status();

            CREATE TRIGGER trg_bloquear_if_exists_bloqueio_proposta_status_on_update
            BEFORE UPDATE ON seguro.propostas_status
            FOR EACH ROW
            WHEN (NEW.id_status IS DISTINCT FROM 8 AND NEW.id_status IS DISTINCT FROM OLD.id_status)
            EXECUTE FUNCTION seguro.fn_bloquear_if_exists_bloqueio_proposta_status();
SQL
        );
    }

    public function down(): void {
        $this->execute(<<<SQL
            DROP TABLE log.bloqueio_proposta_status;
            DROP TRIGGER IF EXISTS trg_bloquear_if_exists_bloqueio_proposta_status ON seguro.proposta_status;
SQL
        );
    }
}