<?php
declare(strict_types=1);

use Phinx\Migration\AbstractMigration;

final class TaskSr50628 extends AbstractMigration
{
    public function up(): void
    {
        $this->upMenuContratosResseguro();
        $this->upPermissoesContratosResseguro();
        $this->upTabela();
        $this->upFuncaoAtivaPropostaStatus();
    }

    public function down(): void
    {
        $this->downFuncaoAtivaPropostaStatus();
        $idContratosResseguro = $this->getIdContratosResseguro();
        $this->execute(<<<SQL
            DELETE FROM sistema.roles_acao WHERE id_acao = {$idContratosResseguro};
            DELETE FROM sistema.roles_acao WHERE id_acao = (SELECT id FROM sistema.acao WHERE id_parent = {$idContratosResseguro} AND ds_action = 'form');
            DELETE FROM sistema.roles_acao WHERE id_acao = (SELECT id FROM sistema.acao WHERE id_parent = {$idContratosResseguro} AND ds_action = 'delete');
            DELETE FROM sistema.acao WHERE id_parent = {$idContratosResseguro};
            DELETE FROM sistema.acao WHERE id = {$idContratosResseguro};
            DROP TABLE seguro.propostas_contratos_resseguro;
            DROP TABLE produto.contratos_resseguro;
SQL
        );
    }

    private function upMenuContratosResseguro()
    {
        $this->execute(<<<SQL
            INSERT INTO sistema.acao (id_usuario_criacao, dt_criacao, ds_label, ds_module, ds_controller, ds_action, id_parent, ds_descricao, fl_tipo)
                VALUES (2068, now(), 'Contrato de Resseguro', 'produto', 'contratosresseguro', 'index', 35, 'Contrato de Resseguro', 'M');
SQL
        );

        $idContratosResseguro = $this->getIdContratosResseguro();

        $this->execute(<<<SQL
            INSERT INTO sistema.acao (id_usuario_criacao, dt_criacao, ds_label, ds_module, ds_controller, ds_action, ds_param, id_parent, ds_image, nr_ordem, fl_tipo)
                VALUES (2068, now(), 'Editar', 'produto', 'contratosresseguro', 'form', 'id', {$idContratosResseguro}, 'edit.png', '0', 'L'),
                       (2068, now(), 'Deletar', 'produto', 'contratosresseguro', 'delete', 'id', {$idContratosResseguro}, 'delete.png', '1', 'L');
SQL
        );
    }

    private function upPermissoesContratosResseguro()
    {
        $idContratosResseguro = $this->getIdContratosResseguro();
        $this->execute(<<<SQL
            INSERT INTO sistema.roles_acao (id_usuario_criacao, dt_criacao, id_role, id_acao)
                VALUES (2068, now(), 20, {$idContratosResseguro}),
                       (2068, now(), 20, (SELECT id FROM sistema.acao WHERE id_parent = {$idContratosResseguro} AND ds_action = 'form')),
                       (2068, now(), 20, (SELECT id FROM sistema.acao WHERE id_parent = {$idContratosResseguro} AND ds_action = 'delete'));
SQL
        );
    }

    private function getIdContratosResseguro()
    {
        $sql = $this->query("SELECT id FROM sistema.acao WHERE ds_label = 'Contrato de Resseguro' AND ds_module = 'produto' AND ds_controller = 'contratosresseguro'");
        $rows = $sql->fetchAll();
        return $rows[0]['id'];
    }

    private function upTabela()
    {
        $this->execute(<<<SQL
            CREATE TABLE produto.contratos_resseguro (
                id SERIAL,
                ds_nome VARCHAR(100) NOT NULL,
                dt_inicio_vigencia DATE NOT NULL,
                dt_termino_vigencia DATE NOT NULL,
                CONSTRAINT pk_contratos_resseguro PRIMARY KEY (id)
            ) INHERITS (public.campos_default);

            CREATE TABLE seguro.propostas_contratos_resseguro (
                id SERIAL,
                id_proposta INT NOT NULL,
                id_contrato_resseguro INT NOT NULL,
                CONSTRAINT pk_propostas_contratos_resseguro PRIMARY KEY (id),
                CONSTRAINT fk_propostas FOREIGN KEY (id_proposta) REFERENCES seguro.propostas (id),
                CONSTRAINT fk_contratos_resseguro FOREIGN KEY (id_contrato_resseguro) REFERENCES produto.contratos_resseguro (id)
            ) INHERITS (public.campos_default);
SQL
        );
    }

    private function upFuncaoAtivaPropostaStatus()
    {
        $this->execute(<<<SQL
            CREATE OR REPLACE FUNCTION seguro.ativa_proposta_status(vid_proposta integer, vid_status integer)
             RETURNS void
             LANGUAGE plpgsql
            AS \$function\$
            DECLARE
                in_id_contrato_resseguro INT;
            BEGIN
                UPDATE seguro.propostas_endosso SET fl_proposta_vigente=false WHERE id_endosso IN (SELECT id_endosso FROM seguro.propostas_endosso WHERE id_proposta=vid_proposta);
                UPDATE seguro.propostas_endosso SET fl_proposta_vigente=true WHERE id_proposta=vid_proposta;

                UPDATE seguro.propostas_status SET fl_ativo=false WHERE id_proposta=vid_proposta;
                UPDATE seguro.propostas_status SET fl_del=true WHERE id_proposta=vid_proposta AND id_status=vid_status;
                INSERT INTO seguro.propostas_status (id_usuario_criacao, id_status, fl_ativo, id_proposta,ds_observacao) VALUES (2068, vid_status, true, vid_proposta,'atualizado por script');
                UPDATE seguro.propostas SET id_status=vid_status WHERE id=vid_proposta;

                -- Se a alteração de status for para APOLICE_EMITIDA ou APOLICE_CANCELADA
                IF vid_status = 8 OR vid_status = 13 THEN
                    -- Valida se já existe vínculo de contrato de resseguro para a proposta informada
                    SELECT pcr.id_contrato_resseguro
                      INTO in_id_contrato_resseguro
                      FROM seguro.propostas_contratos_resseguro pcr
                      JOIN produto.contratos_resseguro cr ON cr.id = pcr.id_contrato_resseguro
                     WHERE (pcr.id_proposta = vid_proposta);

                    IF in_id_contrato_resseguro IS NULL THEN
                        -- Verificamos se a proposta mãe já está vinculada a um contrato
                        SELECT pcr.id_contrato_resseguro
                          INTO in_id_contrato_resseguro
                          FROM seguro.propostas_contratos_resseguro pcr
                          JOIN produto.contratos_resseguro cr ON cr.id = pcr.id_contrato_resseguro
                         WHERE (pcr.id_proposta = (SELECT pr.id_proposta_mae FROM seguro.propostas pr WHERE pr.id = vid_proposta));

                        IF in_id_contrato_resseguro IS NULL THEN
                            -- Busca qual o ID de contrato que a proposta informada se encaixa
                            SELECT cr.id
                              INTO in_id_contrato_resseguro
                              FROM produto.contratos_resseguro cr
                              JOIN (SELECT min(ps.dt_criacao)::date AS dt_emissao_apolice
                                          ,pr.id_proposta_mae
                                      FROM seguro.propostas pr
                                      JOIN seguro.propostas_status ps ON ps.id_proposta = pr.id
                                      JOIN sistema.status st ON st.id = ps.id_status
                                     WHERE st.ds_chave = 'APOLICE_EMITIDA'
                                       AND pr.id_proposta_mae = (SELECT pr.id_proposta_mae FROM seguro.propostas pr WHERE pr.id = vid_proposta)
                                     GROUP BY pr.id_proposta_mae
                              ) AS apolice ON apolice.dt_emissao_apolice BETWEEN cr.dt_inicio_vigencia AND cr.dt_termino_vigencia;
                        END IF;

                        IF in_id_contrato_resseguro IS NOT NULL THEN
                            INSERT INTO seguro.propostas_contratos_resseguro (id_usuario_criacao, dt_criacao, id_proposta, id_contrato_resseguro)
                                VALUES (2068, now(), vid_proposta, in_id_contrato_resseguro);
                        END IF;
                    END IF;
                END IF;
            END;
            \$function\$
SQL
        );
    }

    private function downFuncaoAtivaPropostaStatus()
    {
        $this->execute(<<<SQL

            CREATE OR REPLACE FUNCTION seguro.ativa_proposta_status(vid_proposta integer, vid_status integer)
             RETURNS void
             LANGUAGE plpgsql
            AS \$function\$
            BEGIN

            update seguro.propostas_endosso set fl_proposta_vigente=false where id_endosso in (select id_endosso from seguro.propostas_endosso where id_proposta=vid_proposta);
            update seguro.propostas_endosso set fl_proposta_vigente=true where id_proposta=vid_proposta;

            update seguro.propostas_status set fl_ativo=false where id_proposta=vid_proposta;
            update seguro.propostas_status set fl_del=true where id_proposta=vid_proposta and id_status=vid_status;
            insert into seguro.propostas_status (id_usuario_criacao, id_status, fl_ativo, id_proposta,ds_observacao) values (2068, vid_status, true, vid_proposta,'atualizado por script');
            update seguro.propostas set id_status=vid_status where id=vid_proposta;

            END;
            \$function\$
SQL
        );
    }
}
