<?php
declare(strict_types=1);

use Phinx\Migration\AbstractMigration;

final class Task2402081257 extends AbstractMigration
{
    public function up(): void
    {
        $this->createTempTables();
        $this->alterTableAddColumns();

        $this->atualizaEndossoEPropostasMae();
        $this->atualizaPropostasSemEndosso();
    }

    public function down(): void
    {
        $this->execute(<<<SQL
            ALTER TABLE seguro.informacoes_bancarias
                DROP COLUMN ds_tipo_conta,
                DROP COLUMN fl_conta_conjunta;

            DELETE FROM seguro.informacoes_bancarias 
                WHERE id IN (
                    SELECT
                        id_seguro_informacao_bancaria
                    FROM
                        manutencao.temp_seguro_informacoes_bancarias_endosso
                );

            DELETE FROM seguro.informacoes_bancarias_propostas
                WHERE id IN (
                    SELECT
                        id_seguro_informacao_bancaria_proposta
                    FROM
                        manutencao.temp_informacoes_bancarias_endosso
                );

            DELETE FROM sistema.informacoes_bancarias
            WHERE id IN (
                SELECT
                    id_sistema_informacao_bancaria
                FROM
                    manutencao.temp_informacoes_bancarias_endosso
            );

            DROP TABLE manutencao.temp_seguro_informacoes_bancarias_endosso;
            DROP TABLE manutencao.temp_informacoes_bancarias_endosso;
SQL);
    }

    private function alterTableAddColumns(): void
    {
        $this->execute(<<<SQL
            ALTER TABLE seguro.informacoes_bancarias
                ADD COLUMN ds_tipo_conta CHARACTER(1),
                ADD COLUMN fl_conta_conjunta BOOLEAN;
SQL);
    }

    private function createTempTables(): void
    {
        $this->execute(<<<SQL
            CREATE TABLE manutencao.temp_informacoes_bancarias_endosso(
                id_sistema_informacao_bancaria INTEGER,
                id_seguro_informacao_bancaria_proposta INTEGER
            );

            CREATE TABLE manutencao.temp_seguro_informacoes_bancarias_endosso(
                id_seguro_informacao_bancaria INTEGER
            );
SQL);   
    }

    private function atualizaPropostasSemEndosso(): void
    {
        $rs = $this->fetchAll(<<<SQL
            SELECT
                sp.id as id_proposta, 
                sib.*,
                sibp.fl_conta_conjunta,
                spp.cpf_cnpj,
                segib.id as seguro_id_informacao_bancaria
            FROM
                seguro.propostas sp
            INNER JOIN seguro.propostas_proponentes spp
                ON spp.id_proposta = sp.id
            INNER JOIN seguro.propostas_endosso spe
                ON spe.id_proposta = sp.id
            INNER JOIN produto.produtos pp
                ON pp.id = sp.id_produto
            INNER JOIN seguro.informacoes_bancarias_propostas sibp
                ON sibp.id_proposta = sp.id_proposta_mae
            INNER JOIN sistema.informacoes_bancarias sib
                ON sib.id = sibp.id_informacoes_bancarias
            INNER JOIN seguro.informacoes_bancarias segib
                ON segib.id_proposta = sp.id
                    AND segib.cpf_cnpj = spp.cpf_cnpj
            WHERE
                 sp.id_proposta_mae = sp.id  
                 AND spe.fl_proposta_vigente = true
SQL);

        $flContaConjunta = !empty($row['fl_conta_conjunta']) ? 'true' : 'false';

        foreach ($rs as $row) {
            $this->execute("
                UPDATE seguro.informacoes_bancarias
                SET fl_conta_conjunta = {$flContaConjunta}, ds_tipo_conta = '{$row['ds_tipo_conta']}'
                WHERE id = {$row['seguro_id_informacao_bancaria']}
            ");
        }
    }

    private function atualizaEndossoEPropostasMae(): void
    {
                /**
         * Busca todas as propostas mae e propostas vigentes
         */
        $rs = $this->fetchAll(<<<SQL
            SELECT
                id_proposta_mae,
                sp.id as id_proposta, 
                sib.*,
                sibp.fl_conta_conjunta,
                sibp.fl_titular_conta,
                spp.cpf_cnpj
            FROM
                seguro.propostas sp
            INNER JOIN seguro.propostas_proponentes spp
                ON spp.id_proposta = sp.id
            INNER JOIN seguro.propostas_endosso spe
                ON spe.id_proposta = sp.id
            INNER JOIN produto.produtos pp
                ON pp.id = sp.id_produto
            INNER JOIN seguro.informacoes_bancarias_propostas sibp
                ON sibp.id_proposta = sp.id_proposta_mae
            INNER JOIN sistema.informacoes_bancarias sib
                ON sib.id = sibp.id_informacoes_bancarias
            WHERE
                pp.id_safra >= 25
                AND sp.id_status NOT IN (4, 5, 160, 2, 212, 213, 269, 270, 13)
                AND ((sp.id <> sp.id_proposta_mae AND spe.fl_proposta_vigente = true)
                    OR (sp.id_proposta_mae = sp.id  AND spe.fl_proposta_vigente = false))
            ORDER BY
                id_proposta_mae,
                sp.id
SQL);

        /**
         * Mapeia todas as propostas mae para as propostas vigentes
         */
        $idsPropostaMae = $separator = '';

        foreach ($rs as $row) {
            if (empty($dados[$row['id_proposta_mae']])) {
                $idsPropostaMae .= $separator . $row['id_proposta_mae'];
                $separator = ',';
            }

            $dados[$row['id_proposta']] = $row;
        }

        $tabelaSistemaInfoBancarias = $this->table('sistema.informacoes_bancarias');
        $tabelaSeguroInfoBancarias = $this->table('seguro.informacoes_bancarias');
        $tabelaSeguroInfoBancariasPropostas = $this->table('seguro.informacoes_bancarias_propostas');

        $tabelaTemp1 = $this->table('manutencao.temp_seguro_informacoes_bancarias_endosso');
        $tabelaTemp2 = $this->table('manutencao.temp_informacoes_bancarias_endosso');

        foreach ($dados as $row) {
            if ($row['id_proposta'] == $row['id_proposta_mae']) {
                continue;
            }

            $rowSeguroInfoBancaria = $this->fetchRow("
                SELECT 
                    id
                FROM
                    seguro.informacoes_bancarias 
                WHERE 
                    id_proposta = {$row['id_proposta']}
                    AND cpf_cnpj = '{$row['cpf_cnpj']}'
            ");

            $flContaConjunta = !empty($row['fl_conta_conjunta']) ? 'true' : 'false';
            
            // Insere ou atualiza a tabela seguro.informacoes_bancarias
            if (empty($rowSeguroInfoBancaria)) {
                $tabelaSeguroInfoBancarias->insert(
                    [
                        'id_usuario_criacao' => 2068,
                        'id_proposta' => $row['id_proposta'],
                        'cpf_cnpj' => $row['cpf_cnpj'],
                        'id_banco' => $dados[$row['id_proposta_mae']]['id_banco'],
                        'nu_conta_corrente' => $dados[$row['id_proposta_mae']]['ds_conta'],
                        'nu_digito_conta_corrente' => $dados[$row['id_proposta_mae']]['nu_digito_conta'],
                        'nu_agencia' => $dados[$row['id_proposta_mae']]['ds_agencia'],
                        'nu_digito_agencia' => $dados[$row['id_proposta_mae']]['nu_digito_agencia'],
                        'id_forma_pagamento' => 1,
                        'fl_conta_conjunta' => $row['fl_conta_conjunta'],
                        'ds_tipo_conta' => $row['ds_tipo_conta']
                    ]
                );

                $tabelaSeguroInfoBancarias->saveData();

                $tabelaTemp1->insert(
                    [
                        'id_seguro_informacao_bancaria' => $this->getAdapter()->getConnection()->lastInsertId()
                    ]
                );
                $tabelaTemp1->saveData();
            } else {
                $this->execute("
                    UPDATE seguro.informacoes_bancarias
                    SET fl_conta_conjunta = {$flContaConjunta}, ds_tipo_conta = '{$row['ds_tipo_conta']}'
                    WHERE id = {$rowSeguroInfoBancaria['id']}
                ");
            }

            $this->execute("
                UPDATE seguro.informacoes_bancarias
                SET fl_conta_conjunta = {$flContaConjunta}, ds_tipo_conta = '{$row['ds_tipo_conta']}'
                WHERE id_proposta = {$row['id_proposta_mae']} AND cpf_cnpj = '{$row['cpf_cnpj']}'
            ");

            // Insere na tabela sistema.informacoes_bancarias
            $tabelaSistemaInfoBancarias->insert([
                'id_usuario_criacao' => 2068,
                'id_banco' => $dados[$row['id_proposta_mae']]['id_banco'],
                'ds_agencia' => $dados[$row['id_proposta_mae']]['ds_agencia'],
                'ds_conta' => $dados[$row['id_proposta_mae']]['ds_conta'],
                'ds_observacao' => $dados[$row['id_proposta_mae']]['ds_observacao'],
                'ds_tipo_conta' => $dados[$row['id_proposta_mae']]['ds_tipo_conta'],
                'nu_digito_agencia' => $dados[$row['id_proposta_mae']]['nu_digito_agencia'],
                'nu_digito_conta' => $dados[$row['id_proposta_mae']]['nu_digito_conta']
            ]);
            
            $tabelaSistemaInfoBancarias->saveData();

            $idSistemaInformacaoBancaria = $this->getAdapter()->getConnection()->lastInsertId();

            // Insere na tabela seguro.informacoes_bancarias_propostas
            $tabelaSeguroInfoBancariasPropostas->insert([
                'id_usuario_criacao' => 2068,
                'id_informacoes_bancarias' => $idSistemaInformacaoBancaria,
                'id_proposta' => $row['id_proposta'],
                'fl_titular_conta' =>  $dados[$row['id_proposta_mae']]['fl_titular_conta'],
                'fl_conta_conjunta' =>  $dados[$row['id_proposta_mae']]['fl_conta_conjunta']
            ]);

            $tabelaSeguroInfoBancariasPropostas->saveData();

            $idSeguroInformacaoBancariaProposta = $this->getAdapter()->getConnection()->lastInsertId();

            $tabelaTemp2->insert([
                'id_sistema_informacao_bancaria' => $idSistemaInformacaoBancaria,
                'id_seguro_informacao_bancaria_proposta' => $idSeguroInformacaoBancariaProposta
            ]);

            $tabelaTemp2->saveData();
        }
    }
}
