<?php

class Produto_Model_ValidacoesRestricoes extends Agro_Db_Table_Abstract
{
    protected $_schema = 'produto';
    protected $_name = 'validacoes_restricoes';
    protected $_primary = 'id';
    public $_order = 'id';

    /**
     * @param int $idRestricaoOrigem
     * @param string $novoNome
     * @return void
     * @throws Zend_Db_Table_Exception|Exception
     */
    public function copiar(int $idRestricaoOrigem, string $novoNome): int
    {
        $rowOrigem = $this->find($idRestricaoOrigem)->current()->toArray();
        $rowNovo = $this->save([
            'ds_nome' => $novoNome,
            'id_safra' => $rowOrigem['id_safra'],
        ]);

        $this->copiarCoberturas((int)$rowOrigem['id'], (int)$rowNovo['id']);
        $this->copiarCriterios((int)$rowOrigem['id'], (int)$rowNovo['id']);
        $this->copiarCulturas((int)$rowOrigem['id'], (int)$rowNovo['id']);
        $this->copiarProdutos((int)$rowOrigem['id'], (int)$rowNovo['id']);
        $this->copiarMunicipios((int)$rowOrigem['id'], (int)$rowNovo['id']);

        return (int)$rowNovo['id'];
    }

    /**
     * @param int $idRestricaoOrigem
     * @param int $idRestricaoNovo
     * @return void
     * @throws Exception
     */
    private function copiarCoberturas(int $idRestricaoOrigem, int $idRestricaoNovo): void
    {
        $model = new Produto_Model_ValidacoesRestricoesCoberturas();
        $rowsOrigem = $model->fetchAll("id_validacoes_restricoes = {$idRestricaoOrigem}")->toArray();

        foreach ($rowsOrigem as $row) {
            $model->save([
                'id_validacoes_restricoes' => $idRestricaoNovo,
                'id_cobertura' => $row['id_cobertura'],
            ]);
        }
    }

    /**
     * @param int $idRestricaoOrigem
     * @param int $idRestricaoNovo
     * @return void
     * @throws Exception
     */
    private function copiarCriterios(int $idRestricaoOrigem, int $idRestricaoNovo): void
    {
        $model = new Produto_Model_ValidacoesRestricoesCriterios();
        $rowsOrigem = $model->fetchAll("id_validacoes_restricoes = {$idRestricaoOrigem}")->toArray();

        foreach ($rowsOrigem as $row) {
            $rowNovo = $model->save([
                'id_validacoes_restricoes' => $idRestricaoNovo,
                'id_criterios_restricao' => $row['id_criterios_restricao'],
            ]);

            if ((int)$row['id_criterios_restricao'] === Produto_Model_CriteriosRestricao::ID_DATA_SEMEADURA) {
                $modelSemeadura = new Produto_Model_ValidacoesRestricoesCriteriosSemeadura();
                $rowOrigemSemeadura = $modelSemeadura->fetchRow("id_validacoes_restricoes_criterios = {$row['id']}")
                    ->toArray();
                $modelSemeadura->save([
                    'id_validacoes_restricoes_criterios' => $rowNovo['id'],
                    'dt_semeadura_inicio' => $rowOrigemSemeadura['dt_semeadura_inicio'],
                    'dt_semeadura_fim' => $rowOrigemSemeadura['dt_semeadura_fim'],
                ]);
            }

            if ((int)$row['id_criterios_restricao'] === Produto_Model_CriteriosRestricao::ID_SISTEMA_PLANTIO) {
                $modelSistemaPlantio = new Produto_Model_ValidacoesRestricoesCriteriosSistemaPlantio();
                $rowOrigemSistemaPlantio = $modelSistemaPlantio
                    ->fetchRow("id_validacoes_restricoes_criterios = {$row['id']}")
                    ->toArray();
                $modelSistemaPlantio->save([
                    'id_validacoes_restricoes_criterios' => $rowNovo['id'],
                    'id_sistema_plantio' => $rowOrigemSistemaPlantio['id_sistema_plantio'],
                ]);
            }

            if ((int)$row['id_criterios_restricao'] === Produto_Model_CriteriosRestricao::ID_TIPO_SOLO) {
                $modelTipoSolo = new Produto_Model_ValidacoesRestricoesCriteriosTipoSolo();
                $rowOrigemTipoSolo = $modelTipoSolo
                    ->fetchRow("id_validacoes_restricoes_criterios = {$row['id']}")
                    ->toArray();
                $modelTipoSolo->save([
                    'id_validacoes_restricoes_criterios' => $rowNovo['id'],
                    'id_tipo_solo' => $rowOrigemTipoSolo['id_tipo_solo'],
                ]);
            }
        }
    }

    /**
     * @param int $idRestricaoOrigem
     * @param int $idRestricaoNovo
     * @return void
     * @throws Exception
     */
    private function copiarCulturas(int $idRestricaoOrigem, int $idRestricaoNovo): void
    {
        $model = new Produto_Model_ValidacoesRestricoesCulturas();
        $rowsOrigem = $model->fetchAll("id_validacoes_restricoes = {$idRestricaoOrigem}")->toArray();

        foreach ($rowsOrigem as $row) {
            $model->save([
                'id_validacoes_restricoes' => $idRestricaoNovo,
                'id_cultura' => $row['id_cultura'],
            ]);
        }
    }

    /**
     * @param int $idRestricaoOrigem
     * @param int $idRestricaoNovo
     * @return void
     * @throws Exception
     */
    private function copiarMunicipios(int $idRestricaoOrigem, int $idRestricaoNovo): void
    {
        $model = new Produto_Model_ValidacoesRestricoesMunicipios();
        $rowsOrigem = $model->fetchAll("id_validacoes_restricoes = {$idRestricaoOrigem}")->toArray();

        foreach ($rowsOrigem as $row) {
            $model->save([
                'id_validacoes_restricoes' => $idRestricaoNovo,
                'id_municipio' => $row['id_municipio'],
            ]);
        }
    }

    /**
     * @param int $idRestricaoOrigem
     * @param int $idRestricaoNovo
     * @return void
     * @throws Exception
     */
    private function copiarProdutos(int $idRestricaoOrigem, int $idRestricaoNovo): void
    {
        $model = new Produto_Model_ValidacoesRestricoesProdutos();
        $rowsOrigem = $model->fetchAll("id_validacoes_restricoes = {$idRestricaoOrigem}")->toArray();

        foreach ($rowsOrigem as $row) {
            $model->save([
                'id_validacoes_restricoes' => $idRestricaoNovo,
                'id_produto' => $row['id_produto'],
            ]);
        }
    }

    /**
     * @param int $idValidadoesRestricoes
     * @return void
     */
    public function deletarVinculos(int $idValidadoesRestricoes): void
    {
        $this->deletarVinculosCulturaProdutoCobertura($idValidadoesRestricoes);

        (new Produto_Model_ValidacoesRestricoesMunicipios())->delete(
            $idValidadoesRestricoes,
            'id_validacoes_restricoes'
        );

        $modelValidacoesRestricoesCriterios = new Produto_Model_ValidacoesRestricoesCriterios();
        $rows = $modelValidacoesRestricoesCriterios->fetchAll(
            "id_validacoes_restricoes = {$idValidadoesRestricoes}"
        )->toArray();

        $modelPropostasExcecoes = new Produto_Model_ValidacoesRestricoesCriteriosPropostasExcecoes();

        foreach ($rows as $row) {
            $modelPropostasExcecoes->delete($row['id'], 'id_validacoes_restricoes_criterios');

            if ((int)$row['id_criterios_restricao'] === Produto_Model_CriteriosRestricao::ID_DATA_SEMEADURA) {
                (new Produto_Model_ValidacoesRestricoesCriteriosSemeadura())->delete(
                    $row['id'],
                    'id_validacoes_restricoes_criterios'
                );
            }

            if ((int)$row['id_criterios_restricao'] === Produto_Model_CriteriosRestricao::ID_SISTEMA_PLANTIO) {
                (new Produto_Model_ValidacoesRestricoesCriteriosSistemaPlantio())->delete(
                    $row['id'],
                    'id_validacoes_restricoes_criterios'
                );
            }

            if ((int)$row['id_criterios_restricao'] === Produto_Model_CriteriosRestricao::ID_TIPO_SOLO) {
                (new Produto_Model_ValidacoesRestricoesCriteriosTipoSolo())->delete(
                    $row['id'],
                    'id_validacoes_restricoes_criterios'
                );
            }
        }

        $modelValidacoesRestricoesCriterios->delete($idValidadoesRestricoes, 'id_validacoes_restricoes');
    }

    /**
     * @param int $idValidadoesRestricoes
     * @return void
     */
    public function deletarVinculosCulturaProdutoCobertura(int $idValidadoesRestricoes): void
    {
        (new Produto_Model_ValidacoesRestricoesCulturas())->delete($idValidadoesRestricoes, 'id_validacoes_restricoes');
        (new Produto_Model_ValidacoesRestricoesProdutos())->delete($idValidadoesRestricoes, 'id_validacoes_restricoes');
        (new Produto_Model_ValidacoesRestricoesCoberturas())->delete(
            $idValidadoesRestricoes,
            'id_validacoes_restricoes'
        );
    }

    public function getData($where = false)
    {

        $select = $this->select()->setIntegrityCheck(false)->distinct();
        $select->from(['pvr' => "{$this->_schema}.{$this->_name}"])
        ->joinLeft(['pvrco' => 'produto.validacoes_restricoes_coberturas'],'pvrco.id_validacoes_restricoes = pvr.id',false)
        ->joinLeft(['pvrcu' => 'produto.validacoes_restricoes_culturas'],'pvrcu.id_validacoes_restricoes = pvr.id',false)
        ->joinLeft(['pvrm' => 'produto.validacoes_restricoes_municipios'],'pvrm.id_validacoes_restricoes = pvr.id',false)
        ->joinLeft(['sm' => 'sistema.municipios'], 'sm.id = pvrm.id_municipio', false)
        ->joinLeft(['pvrp' => 'produto.validacoes_restricoes_produtos'],
                'pvrp.id_validacoes_restricoes = pvr.id',
                false
            )
            ->joinLeft(
                ['pvrcr' => 'produto.validacoes_restricoes_criterios'],
                'pvrcr.id_validacoes_restricoes = pvr.id',
                false
            )
            ->joinLeft(
                ['pvrcpe' => 'produto.validacoes_restricoes_criterios_propostas_excecoes'],
                'pvrcpe.id_validacoes_restricoes_criterios = pvrcr.id',
                false
            );

        if ($this->_order) {
            $select->order($this->_order);
        }

        $this->getWhere($select, $where);

        return $select;
    }

    /**
     * @param array $dados
     * @return false|Zend_Db_Table_Row_Abstract|null
     * @throws Exception
     */
    public function save(array $dados)
    {
        if (empty(trim($dados['ds_nome']))) {
            throw new Exception('Nome não informado.');
        }

        if (empty($dados['id_safra'])) {
            throw new InvalidArgumentException('Safra não informada.');
        }

        if ($this->nomeDuplicado((int)$dados['id'], $dados['ds_nome'])) {
            throw new Exception('Nome informado já encontra-se cadastrado para outra restrição.');
        }

        $row = $this->getRow($dados['id']);
        $row->ds_nome = $dados['ds_nome'];
        $row->id_safra = $dados['id_safra'];

        if (array_key_exists('fl_ativo', $dados)) {
            $row->fl_ativo = $dados['fl_ativo'];
        }

        if (!$row->save()) {
            throw new Exception('Erro ao salvar a restrição.');
        }

        return $row;
    }

    /**
     * @param int|null $id
     * @param string $nomeRestricao
     * @return bool
     */
    private function nomeDuplicado(?int $id, string $nomeRestricao): bool
    {
        $where = "trim(ds_nome) = trim('{$nomeRestricao}')";

        if (!empty($id)) {
            $where .= " AND id <> {$id}";
        }

        return !empty($this->fetchRow($where));
    }

    /**
    * Obtém as restrições de validação com base nos parâmetros fornecidos.
    *
    * Busca restrições configuradas específicas com base nos parâmetros de cobertura, cultura, município, produto e safra.
    * @param array $arr Array associativo contendo os seguintes parâmetros:
    *  - int 'idCobertura' ID da cobertura.
    *  - int 'idCultura' ID da cultura.
    *  - int 'idMunicipio' ID do município.
    *  - int 'idSafra' ID da safra.
    *
    * @return array|false Retorna um array de resultados se houver registros correspondentes,
    *                     ou false se nenhum registro for encontrado.
    */
    public function getRestricoes(array $arr)
    {
        $sql = "SELECT DISTINCT(pvr.id) FROM produto.validacoes_restricoes as pvr 
        LEFT JOIN produto.validacoes_restricoes_coberturas as pvrco on pvrco.id_validacoes_restricoes = pvr.id
        LEFT JOIN produto.validacoes_restricoes_culturas as pvrcu ON pvrcu.id_validacoes_restricoes = pvr.id
        LEFT JOIN produto.validacoes_restricoes_municipios as pvrm ON pvrm.id_validacoes_restricoes = pvr.id
        LEFT JOIN produto.validacoes_restricoes_produtos as pvrp ON pvrp.id_validacoes_restricoes = pvr.id
        LEFT JOIN sistema.municipios as sm on pvrm.id_municipio = sm.id
        LEFT JOIN produto.validacoes_restricoes_criterios as pvrcr ON pvrcr.id_validacoes_restricoes = pvr.id
        LEFT JOIN produto.validacoes_restricoes_criterios_propostas_excecoes as pvrcpe on pvrcpe.id_validacoes_restricoes_criterios = pvrcr.id
        LEFT JOIN produto.safras as safras ON safras.id = pvr.id_safra
        where pvrco.id_cobertura = {$arr['idCobertura']} and pvrcu.id_cultura = {$arr['idCultura']}  AND pvr.fl_ativo = 't' AND pvrm.id_municipio = {$arr['idMunicipio']} AND safras.id = {$arr['idSafra']}";
        $res = $this->_db->query($sql)->fetchAll();
        
        if(!$res){
            return false;
        }
        return $res;
    }

    public function getRestricoesSemCobertura(array $arr)
    {
        $sql = "SELECT DISTINCT(pvr.id) FROM produto.validacoes_restricoes as pvr 
        LEFT JOIN produto.validacoes_restricoes_coberturas as pvrco on pvrco.id_validacoes_restricoes = pvr.id
        LEFT JOIN produto.validacoes_restricoes_culturas as pvrcu ON pvrcu.id_validacoes_restricoes = pvr.id
        LEFT JOIN produto.validacoes_restricoes_municipios as pvrm ON pvrm.id_validacoes_restricoes = pvr.id
        LEFT JOIN produto.validacoes_restricoes_produtos as pvrp ON pvrp.id_validacoes_restricoes = pvr.id
        LEFT JOIN sistema.municipios as sm on pvrm.id_municipio = sm.id
        LEFT JOIN produto.validacoes_restricoes_criterios as pvrcr ON pvrcr.id_validacoes_restricoes = pvr.id
        LEFT JOIN produto.validacoes_restricoes_criterios_propostas_excecoes as pvrcpe on pvrcpe.id_validacoes_restricoes_criterios = pvrcr.id
        LEFT JOIN produto.safras as safras ON safras.id = pvr.id_safra
        where pvrco.id_cobertura IS NULL 
        AND pvrcu.id_cultura = {$arr['idCultura']} 
        AND pvrm.id_municipio = {$arr['idMunicipio']} 
        AND safras.id = {$arr['idSafra']}
        AND pvr.fl_ativo = 't'
        AND pvrp.id_produto = {$arr['idProduto']}";
        
       /* $sql = "SELECT DISTINCT(pvr.id) FROM produto.validacoes_restricoes as pvr 
        LEFT JOIN produto.validacoes_restricoes_culturas as pvrcu ON pvrcu.id_validacoes_restricoes = pvr.id
        LEFT JOIN produto.validacoes_restricoes_municipios as pvrm ON pvrm.id_validacoes_restricoes = pvr.id
        LEFT JOIN produto.validacoes_restricoes_produtos as pvrp ON pvrp.id_validacoes_restricoes = pvr.id
        LEFT JOIN sistema.municipios as sm on pvrm.id_municipio = sm.id
        LEFT JOIN produto.validacoes_restricoes_criterios as pvrcr ON pvrcr.id_validacoes_restricoes = pvr.id
        LEFT JOIN produto.validacoes_restricoes_criterios_propostas_excecoes as pvrcpe on pvrcpe.id_validacoes_restricoes_criterios = pvrcr.id
        LEFT JOIN produto.safras as safras ON safras.id = pvr.id_safra
        where pvrcu.id_cultura = {$arr['idCultura']} AND pvrm.id_municipio = {$arr['idMunicipio']} AND safras.id = {$arr['idSafra']}";*/
        $res = $this->_db->query($sql)->fetchAll();
        
        if(!$res){
            return false;
        }
        return $res;
    }


    // Retorna um array contendo os IDs das validações e os IDs dos critérios correspondentes que não foram aprovados.
    public function validar(array $validacoes, array $unidade, $idProposta): array
    {
        $modelCriterio                      = new Produto_Model_CriteriosRestricao();
        $modelValidacaoRestricaoCriterio    = new Produto_Model_ValidacoesRestricoesCriterios();
        $erros = [];
        $criteriosFeridos = [];

        foreach ($validacoes as $validacao) {
            $criteriosConfigurados = $validacao['configuracao'];
            foreach ($criteriosConfigurados as $configuracao) {
                
                $idCriterio = !Agro_Util::filterVariable($configuracao['id_criterio']) ? 0 : (int)$configuracao['id_criterio'];
                $erro = $modelValidacaoRestricaoCriterio->validar($idCriterio, $unidade, $configuracao, $idProposta);
                
                if ($erro && !in_array($idCriterio, $criteriosFeridos)) {
                    $mensagemErro = $modelCriterio->getRow($idCriterio)->toArray()['ds_mensagem'];
                    $erros[]            = $mensagemErro;
                    $criteriosFeridos[] = $idCriterio;
                }
            }
        }
        
        return $erros;
    }

}
