<?php

class Seguro_Model_VistoriaPrevia extends Agro_Db_Table_Abstract {
    const EXCEPTION_PROPOSTAS_COM_SINISTRO = 1;

    const DS_CHAVE_VP_STATUS_ALTERACAO_AGUARDANDO_ENDOSSO = 'AGUARDANDO_ENDOSSO';
    const DS_CHAVE_VP_STATUS_ALTERACAO_ENDOSSO_EFETIVADO = 'ENDOSSO_EFETIVADO';

    const ID_STATUS_VP_AGUARDANDO_VISTORIA = 70;
    const ID_STATUS_VP_CANCELADA = 227;
    const ID_STATUS_VP_DISPENSADA = 225;
    const ID_STATUS_VP_ENC = 66;
    const ID_STATUS_VP_TRANSMITIDA = 71;
    const ID_STATUS_VP_TRANSMITIDA_SEM_FOTOS = 226;

    const ID_STATUS_VP_ANALISE_AGUARDANDO_NOVA_VISTORIA = 179;
    const ID_STATUS_VP_ANALISE_ANALISANDO = 170;
    const ID_STATUS_VP_ANALISE_ANALISE_DISPENSADA = 234;
    const ID_STATUS_VP_ANALISE_CONCLUIDA_AUMENTO = 174;
    const ID_STATUS_VP_ANALISE_CONCLUIDA_CANC = 176;
    const ID_STATUS_VP_ANALISE_CONCLUIDA_COM_ALT_SEM_MOV = 173;
    const ID_STATUS_VP_ANALISE_CONCLUIDA_RED = 175;
    const ID_STATUS_VP_ANALISE_CONCLUIDA_SEM_ALT = 178;
    const ID_STATUS_VP_ANALISE_NAO_ANALISADO = 169;
    const ID_STATUS_VP_ANALISE_NAO_RECEBIDA = 233;
    const ID_STATUS_VP_ANALISE_PENDENCIA_CORRETOR = 172;
    const ID_STATUS_VP_ANALISE_PENDENCIA_PERITO = 171;
    const ID_STATUS_VP_ANALISE_PENDENCIA_PERITO_CORRETOR = 177;

	protected $_schema = 'seguro';
	protected $_name = 'propostas_vistorias_previas';
	protected $_primary = 'id_vistoria';
	public $_order = array('sub.data_semeadura', 'prod.ds_nome_abreviado', 'e.ds_sigla', 'm.ds_nome_municipio', 'sub.lmga_total');


	public function save(array $dados, $useTabletRule = false) {
		try{
			//pega o status "Encaminhado"
			$id_status = $this->getIdStatusEncaminhado();
			$ModelVP = new Seguro_Model_VistoriaPreviaEmpresa();
            $i = 0;
            $propostasComAvisoAceito = [];

			foreach($dados['id_propostas'] as $id_proposta){
				//pode haver mais de uma vistoria por proposta, dessa forma foi alterado para informar o id_proposta_vistoria = id da vistoria prévia
				$id_proposta_vistoria = null;
				$idEmpresa = $id_proposta['id_empresa_proposta'];

				if (is_array($id_proposta)) {
					$id_proposta_vistoria = $id_proposta['id_proposta_vistoria'];
					$id_proposta = $id_proposta['id_proposta'];
				}

				if (isset($dados['validarExistenciaSinistro']) && $dados['validarExistenciaSinistro'] === 'true') {
                    /**
                     * Valida se há um aviso aceito para uma empresa. Neste caso, só é possível encaminhar individualmente
                     */
                    $rowsEmpresaProcesso = (new Sinistro2_Model_Processos())->getEmpresaProcesso(
                      $id_proposta, [
                        Sinistro2_Model_Processos::ID_STATUS_ABERTO_LIQUIDACAO,
                        Sinistro2_Model_Processos::ID_STATUS_ABERTO_REGULACAO,
                        Sinistro2_Model_Processos::ID_STATUS_ABERTO_SEM_EMPRESA
                      ]
                    );

                    if (!empty($rowsEmpresaProcesso) && (int) $rowsEmpresaProcesso['id'] !== (int) $dados['id_empresa']) {
                        $propostasComAvisoAceito[] = $rowsEmpresaProcesso['id_proposta_mae'];
                        continue;
                    }

                    if (!empty($rowsEmpresaProcesso) && (int) $rowsEmpresaProcesso['id'] === (int) $dados['id_empresa'] && count($dados['id_propostas']) > 1) {
                        $propostasComAvisoAceito[] = $rowsEmpresaProcesso['id_proposta_mae'];
                        continue;
                    }
                }

				if((!$useTabletRule || !$this->canCreateNewByTabletRule($id_proposta, $id_proposta_vistoria)) && !$ModelVP->temLaudoDigitado($id_proposta, $id_proposta_vistoria)) { //valida a regra opcional do tablet
					$id_vistoria = $this->getIdVistoria($id_proposta, $id_proposta_vistoria);
				}else{
					$rowMae = $this->getRow($this->getIdVistoria($id_proposta, $id_proposta_vistoria));
					$id_vistoria = '';
				}

				//dados para tabela sistema.vistorias//
				$ModelVistorias = new Sistema_Model_Vistorias();
				$dados['id'] 		= $id_vistoria;
				$dados['id_tipo']	= 1;
				$dados['dt_inicio']	= null;
				$dados['dt_fim']	= null;

				$id_vistoria = $ModelVistorias->save($dados);
				//-----//

				//salva a empresa
				$ModelVistoriaEmpresas = new Sistema_Model_VistoriasEmpresas();
				$ModelVistoriaEmpresas->delete($id_vistoria);
				$dados['id_vistoria'] = $id_vistoria;

				$ModelVistoriaEmpresas->save($dados);
				//---//

				$Funcionarios = new Sistema_Model_Funcionarios();
					$vistoriadores = $Funcionarios->getVistoriadores($dados['id_empresa']);

					$ModelVistoriador = new Sistema_Model_VistoriasFuncionarios();
					$ModelVistoriador->delete($dados['id_vistoria']);
					if (count($vistoriadores) == 1) {
						$vistoriadores = current($vistoriadores);
						$dados['id_funcionario'] = $vistoriadores['id'];

						$ModelVistoriador->save($dados);
					}

					//deleta o agendamento pois a vistoria foi reencaminhada
					$Agendamento = new Sistema_Model_VistoriasAgendamentos();
					$Agendamento->deleteVistoriaAgendamento($id_vistoria);
					//----//

					// //data de encaminhamento
					$hoje = new Datetime;

				//salva a relação proposta/vistoria/status
				$Row = $this->getRow($id_vistoria);
				$Row->id_proposta = $id_proposta;
				$Row->id_vistoria = $id_vistoria;
				$Row->id_status = $id_status;
                $Row->ds_motivo = $dados['ds_motivo'];
                $Row->fl_nova_vistoria_custo_perito = $dados['fl_nova_vistoria_custo_perito'];
				$Row->dt_prazo_agendamento = $this->getDataPrazoAgendamento($hoje, $id_proposta)->format('Y-m-d');
				//se for transferência, que cancela a vistoria anterior, copia o id da vistoria mãe tbm
				$statusModel = new Sistema_Model_Status;
				if (isset($rowMae) && $rowMae->id_status == $statusModel->getId('CANCELADA', 'VP') && $rowMae->id_vistoria_mae) {
					$Row->id_vistoria_mae = $rowMae->id_vistoria_mae;
				}
				if (isset($dados['id_propostas_endossos']) && !empty($dados['id_propostas_endossos'])) {
                	$Row->id_proposta_solicitacao = $dados['id_propostas_endossos'][$i];
				}
				if ($dados['id_vistoria_mae']) {
					$Row->id_vistoria_mae = $dados['id_vistoria_mae'];
				}
				//recebe TRUE ao aceitar um aviso de sinistro com cobertura de replantio
				$Row->fl_vistoria_replantio = $dados['fl_vistoria_replantio'] ? $dados['fl_vistoria_replantio'] : 'false';

                if (array_key_exists('id_status_alteracao', $dados)) {
                    $Row->id_status_alteracao = $dados['id_status_alteracao'];
                }
				
                if ($Row->save()) {

                    //Salva na tabela histórico em nova vistoria
                    $ModelVistoriasHistorico = new Seguro_Model_VistoriaPreviaHistorico();
                    $dados['id_proposta_vistoria'] = $Row->id;
                    $dados['id_status'] = $Row->id_status;
                    $dados['id_status_analise'] = $Row->id_status_analise;
                    $dados['id_empresa_historico'] = $ModelVistoriaEmpresas->id;
                    $dados['id_status_alteracao'] = $Row->id_status_alteracao;

                    $ModelVistoriasHistorico->save($dados);

					//Salva na tabela histórico na vistoria anterior (cancelada)
					if ($id_proposta_vistoria) {
					    $status = $statusModel->getId('CANCELADA', 'VP');
					    $statusAnalise = $Row->id_status_analise;
					    $statusTransmissao = [
                          Sistema_Model_Status::VP_TRANSMITIDA,
                          Sistema_Model_Status::VP_TRANSMITIDA_SEM_FOTOS
                        ];

					    $rowVistoriasHistorico = $ModelVistoriasHistorico->getHistoricoByVistoria($id_proposta_vistoria)->toArray();

					    if (!empty($rowVistoriasHistorico) && in_array((int) $rowVistoriasHistorico[0]['id_status_historico'], $statusTransmissao)) {
                            $status = Sistema_Model_Status::VP_TRANSMITIDA;
                            $statusAnalise = $rowVistoriasHistorico[0]['id_status_analise'];
                        }

						$dados['id_proposta_vistoria'] = $id_proposta_vistoria;
						$dados['id_status'] = $status;
						$dados['id_status_analise'] = $statusAnalise;
						$dados['id_empresa_historico'] = $idEmpresa;

						$ModelVistoriasHistorico->save($dados);
					}
                }

                $i++;
			}

			if (!empty($propostasComAvisoAceito)) {
			    throw new Exception(
			      "As propostas listadas abaixo não foram encaminhadas pois possuem comunicado de sinistro:\n" . implode(', ', $propostasComAvisoAceito),
                  self::EXCEPTION_PROPOSTAS_COM_SINISTRO
                );
            }

			return true;

		} catch (Exception $e) {
			throw $e;
		}
	}

	/**
	 * Regra para validar se cria nova vistoria prévia conforme o status tablet.
	 * Quando o status tablet é Aguardando Vistoria, já é persitido status novo da vistoria atual para cancelado 
	 *
	 * @param int $id_proposta 
	 * @param int $id_proposta_vistoria
	 * @throws Zend_Exception dispara para cancelar a validação da regra caso a vistoria esteja com status tablet cancelado e status dispensado
	 * @return boolean
	 */
	private function canCreateNewByTabletRule($id_proposta, $id_proposta_vistoria) {
		$row = $this->getRow($this->getIdVistoriaByEndosso($id_proposta, $id_proposta_vistoria));

		$statusModel = new Sistema_Model_Status;
		$idStatusTabletCancelada = $statusModel->getId('CANCELADA', 'VP_TABLET');
		$idStatusCancelada = $statusModel->getId('CANCELADA', 'VP');

		//caso a vistoria esteja com status tablet cancelada e status cancelada, não deixa transferir
		if ($row->id_status_tablet == $idStatusTabletCancelada && $row->id_status == $idStatusCancelada) {
			//throw new Zend_Exception("Não é possível executar esta ação para esta Vistoria Prévia!");
		}

		//quando a vistoria prévia está com o status 'Aguardando Vistoria' ou 'Encaminhada', a atual vai para cancelada
		if ($row->id_status == $statusModel->getId('AGUARDANDO_VISTORIA', 'VP') || $row->id_status == $statusModel->getId('ENC', 'VP')) {
			$row->id_status_tablet = $idStatusTabletCancelada;
			$row->id_status = $idStatusCancelada;

			$row->save();
		}

		return true;
	}

	/**
	 * Retorna a data de prazo de agendamento, comparando a data de plantio ou a data de semeadura, com a data do encaminhamento. A maior delas, adiciona 5 dias
	 * 
	 * @param Datetime $dataEncaminhamento 
	 * @param int $idProposta 
	 * @return Datetime
	 */
	public function getDataPrazoAgendamento(Datetime $dataEncaminhamento, $idProposta) {
		$ItensSegurados = new Seguro_Model_ItensSegurados();
		$itensProposta = $ItensSegurados->getMaxDatesByProposta($idProposta);

		$dataPrazoAgendamento = null;
		if (!empty($itensProposta['dt_plantio'])) {
			$dataPrazoAgendamento = new Datetime($itensProposta['dt_plantio']);
		} else if (!empty($itensProposta['dt_semeadura'])) {
			$dataPrazoAgendamento = new Datetime($itensProposta['dt_semeadura']);
		}

		if ($dataPrazoAgendamento) {
			//a diferença deve ser calculada entre a data do plantio
			$diferenca = $dataPrazoAgendamento->diff($dataEncaminhamento);
			// se dataEncaminhamento é maior que a data de prazo agendamento, então o agendamento é apartir da dataEncaminhamento
			if ($diferenca->days > 0 && $diferenca->invert == 0) {
				$dataPrazoAgendamento = $dataEncaminhamento;
			}
		} else {
			$dataPrazoAgendamento = $dataEncaminhamento;
		}
		$dataPrazoAgendamento->add(new DateInterval('P5D'));

		return $dataPrazoAgendamento;
	}

	/**
	 * Utiliza da regra do método getDataPrazoAgendamento e persiste no banco.
	 * 
	 * @param int $idProposta 
	 * @param int $idPropostaMae 
	 * @param Datetime|null $dataEncaminhamento 
	 * @return int
	 */
	public function updateDataPrazoAgendamento($idProposta, $idPropostaMae, Datetime $dataEncaminhamento = null) {
		$idVistoria = $this->getIdVistoria($idPropostaMae);

		if (!$idVistoria)
			return;
		
		$row = $this->getRow($idVistoria);
		if (!$row)
			return;

		if (!$dataEncaminhamento) {
			if ($row->dt_alteracao) {
				$dataEncaminhamento =  new Datetime($row->dt_alteracao);
			} else {
				$dataEncaminhamento =  new Datetime($row->dt_criacao);
			}
		}

		$row->dt_prazo_agendamento = $this->getDataPrazoAgendamento($dataEncaminhamento, $idProposta)->format('Y-m-d');
		
		return $row->save();
	}

	public function dispensar($dados) {
		try {
			$VistoriaPreviaHistorico = new Seguro_Model_VistoriaPreviaHistorico();
			$Status = new Sistema_Model_Status();
			$ModelVP = new Seguro_Model_VistoriaPreviaEmpresa();
			$idStatus = $Status->getId('DISPENSADA', 'VP');
			$idStatusTabletCancelada = $Status->getId('CANCELADA', 'VP_TABLET');
			$dados['ds_motivo'] = 'Alteração de Status.';
			$i = 0;
			$Model = new Seguro_Model_VistoriaPrevia();
			$Model->getAdapter()->beginTransaction();

			if(is_array($dados['id_propostas'])){
				foreach($dados['id_propostas'] as $id_proposta){
						//pode haver mais de uma vistoria por proposta, dessa forma foi alterado para informar o id_proposta_vistoria = id da vistoria prévia
					$id_proposta_vistoria = null;
					if (is_array($id_proposta)) {
						$id_proposta_vistoria = $id_proposta['id_proposta_vistoria'];
						$id_proposta = $id_proposta['id_proposta'];
					}
					if(!$ModelVP->temLaudoDigitado($id_proposta, $id_proposta_vistoria) && $this->canDispensar($id_proposta, $id_proposta_vistoria)) {
						$id_vistoria = $this->getIdVistoriaByEndosso($id_proposta, $id_proposta_vistoria);
					}else{
						throw new Zend_Exception("Vistoria Prévia não pode ser dispensada ou já está dispensada!");
						
					}

					$ModelVistorias = new Sistema_Model_Vistorias();
					$dados['id'] 		= $id_vistoria;
					$dados['id_tipo']	= 1;
					$dados['dt_inicio']	= null;
					$dados['dt_fim']	= null;

					$id_vistoria = $ModelVistorias->save($dados);

					$Row = $this->getRow($id_vistoria);
					$Row->id_status = $idStatus;
					$Row->id_status_tablet = $idStatusTabletCancelada;
					$Row->id_proposta = $id_proposta;
					$Row->id_vistoria = $id_vistoria;
					$Row->ds_motivo = $dados['ds_motivo'];
					$Row->id_proposta_solicitacao = $dados['id_propostas_endossos'][$i];

                    if($Row->save()) {
                        //salvando histório
                        $data = $dados;
                        $data['id_proposta_vistoria'] = $Row->id;
						$data['id_status'] = $Row->id_status;
						$data['id_status_analise'] = $Row->id_status_analise;
						$data['id_empresa_historico'] = 20; //agrobrasil
						$retornoHistorico = $VistoriaPreviaHistorico->save($data);
                        if (!$retornoHistorico instanceof Zend_Db_Table_Row) {
							throw new Exception($retornoHistorico);
						}
                    }

					$i++;
				}
			}

			$Model->getAdapter()->commit();
			return true;
		} catch (Zend_Exception $ze) {
			throw $ze;
		} catch (Exception $e) {
			$Model->getAdapter()->rollback();
			return false;
		}
	}

	public function canDispensar($id_proposta, $id_proposta_vistoria) {
		$row = $this->getRow($this->getIdVistoria($id_proposta, $id_proposta_vistoria));
		$statusModel = new Sistema_Model_Status;

		if ($row->id_status == $statusModel->getId('DISPENSADA', 'VP')) {
			return false;
		}

		return true;
	}

	public function getIdVistoria($id_proposta, $id_proposta_vistoria = null){
		$select = $this->select()->setIntegrityCheck(false);
		$select->from(array('vp'=>'seguro.propostas_vistorias_previas'),'vp.id_vistoria');
		$select->join(array('vis'=>'sistema.vistorias'),'vis.id = vp.id_vistoria',false);
		$select->where("vp.id_proposta = ?", $id_proposta);
		if ($id_proposta_vistoria) {
			$select->where("vp.id = ?", $id_proposta_vistoria);
		}

		$id_vistoria =  $this->_db->fetchOne($select);

    	return $id_vistoria;
	}

	public function getIdVistoriaByEndosso($id_proposta, $id_proposta_vistoria = null){
		$select = $this->select()->setIntegrityCheck(false);
		$select->from(array('vp'=>'seguro.propostas_vistorias_previas'),'vp.id_vistoria');
		$select->join(array('vis'=>'sistema.vistorias'), 'vis.id = vp.id_vistoria',false);
		$select->join(array('p' => 'seguro.propostas'), 'vp.id_proposta = p.id', false);
		$select->join(array('pe' => 'seguro.propostas_endosso'), 'p.id_endosso = pe.id_endosso', false);
		$select->where("pe.id_proposta = ?", $id_proposta);
		if ($id_proposta_vistoria) {
			$select->where("vp.id = ?", $id_proposta_vistoria);
		}

		$id_vistoria =  $this->_db->fetchOne($select);

    	return $id_vistoria;
	}

	public function getIdVistorias($id_proposta, $id_proposta_vistoria = null){
		$select = $this->select()->setIntegrityCheck(false);
		$select->from(array('vp'=>'seguro.propostas_vistorias_previas'),'vp.id_vistoria');
		$select->join(array('vis'=>'sistema.vistorias'),'vis.id = vp.id_vistoria',false);
		$select->where("vp.id_proposta = ?", $id_proposta);
		if ($id_proposta_vistoria) {
			$select->where("vp.id = ?", $id_proposta_vistoria);
		}

		$id_vistoria =  $this->_db->fetchAll($select);

    	return $id_vistoria;
	}

	public function getIdStatusEncaminhado(){
		$select = $this->select()->setIntegrityCheck(false);
		$select->from(array('s'=>'sistema.status'),'s.id');
		$select->join(array('ts'=>'sistema.tipo_status'),'ts.id = s.id_tipo_status',false);
		$select->where("ts.ds_chave = ?", "VP");
		$select->where("s.cd_status = ?", 1);

		$id_status =  $this->_db->fetchOne($select);

		return $id_status;
	}


	public function getData($where=false) {

        // verifica se foi informado filtro de safra para também adicioná-lo na criação da tabela temporária
        foreach($where as $clause) {
            if ($clause['field'] == 'saf.id') {
                $AND = " AND prod.id_safra ".$clause['operator']." ".$clause['value']." ";
            }

            if ($clause['field'] == 'prod.id') {
            	$AND .= " AND ". $clause['field']." ".$clause['operator']." ".$clause['value'];
            }

            if ($clause['field'] == 'prodg.id') {
            	$AND .= " AND ". $clause['field']." ".$clause['operator']." ".$clause['value'];
            }

            //adicionado para melhorar o desempenho quando filtra por proposta
            if ($clause['field'] == 'p.id') {
            	$AND .= " AND ". $clause['field']." ".$clause['operator']." ".$clause['value'];
            }

            if ($clause['field'] == 'p.nr_apolice') {
            	$AND .= " AND ". $clause['field']." ".$clause['operator']." ".$clause['value'];
            }
        }
       
        $this->_db->query("
       					   CREATE temp
			                TABLE boletos_temp AS (
			               SELECT CASE WHEN fl_pago = true THEN 'Sim' ELSE 'Não' END as fl_boleto
			                      ,dt_vencimento
			                      ,id_proposta
			                      ,p.id_endosso
										        ,fl_pago
			                 FROM seguro.proposta_boletos pb
			                 JOIN seguro.propostas p
			                   ON p.id = pb.id_proposta
			                WHERE nr_parcela = 1
			                  AND pb.fl_ativo = true
			                  AND seguro.nr_endosso(id_proposta,p.id_endosso) = 0
							 )");
                                
		//cria tabela temporária para buscar alguns dados
		$this->_db->query(
							"CREATE temp TABLE itens_segurados_temp AS (
                                SELECT
                                	its.id_proposta,
                                	its.vl_lmga AS lmga_total,
                                	itsc.data_semeadura_validacao,
                                	itsc.data_semeadura
                                FROM 
                                    sumario.itens_segurados its 
                                    inner join (
                                	select 
                                	    sis.id_proposta,
                                	    CASE
                                		WHEN max(sisc.dt_semeadura) is not null THEN max(sisc.dt_semeadura) ELSE '1900-01-01'
                                	    END AS data_semeadura_validacao,
                                	    max(sisc.dt_semeadura) as data_semeadura
                                	from
                                	    seguro.itens_segurados sis 
                                	    inner join seguro.itens_segurados_complemento sisc on sisc.id_item_segurado = sis.id
                                	group by 
                                	    sis.id_proposta ) itsc on itsc.id_proposta = its.id_proposta	

                            )"
						);
		
		$this->_db->query(
		    "CREATE temp TABLE vistorias_previas_temp AS (
		          SELECT
		              id_endosso, id_vistoria, vp.id, vp.id_status
		          FROM
		              seguro.propostas p
		          INNER JOIN seguro.propostas_vistorias_previas vp ON vp.id_proposta = p.id
		    )"
		 );
		
        $subselect = $this->select()->setIntegrityCheck(false);
        $subselect->from(array('pe' => 'seguro.propostas_endosso'), array(id_proposta, id_endosso));
        $subselect->where('pe.fl_proposta_vigente = true');

		$select = $this->select()->setIntegrityCheck(false);
		$select->from(array('p'=>'seguro.propostas'),array('id','id_proposta_mae', 'id_endosso', 'id_status', 'dt_vigencia_inicio', 'id_usuario_criacao', 'id_produto', 'ds_status_seguradora', 'nr_digito_verificador', 'nr_apolice', 'ds_identificador_seguradora', 'id_versao',  'id_proposta_endossada'));
		$select->join(array('pe' => $subselect),  'pe.id_proposta = p.id', 'pe.id_proposta as id_proposta_endosso');
		$select->join(array('sub'=>'itens_segurados_temp'),'sub.id_proposta = p.id', array('sub.lmga_total','sub.data_semeadura'));
		$select->join(array('pp'=>'seguro.propostas_propriedades'),'p.id = pp.id_proposta', '');
		$select->join(array('prop'=>'seguro.propostas_proponentes'),'p.id = prop.id_proposta', 'ds_nome_proponente');
		$select->join(array('sst'=>'sistema.status'),'sst.id = p.id_status',null);
		$select->join(array('prod'=>'produto.produtos'),'p.id_produto = prod.id', 'prod.ds_nome_abreviado');
		$select->join(array('prodg'=>'produto.produtos_geral'),'prod.id_produto_geral = prodg.id', false);
		$select->join(array('saf'=>'produto.safras'),'saf.id = prod.id_safra', false);
		$select->join(array('m'=>'sistema.municipios'),'pp.id_municipio = m.id', 'm.ds_nome_municipio');
		$select->join(array('e'=>'sistema.estados'),'m.id_estado = e.id', 'e.ds_sigla');
		$select->join(array('usu'=>'sistema.usuarios'),'usu.id = p.id_usuario_criacao', 'usu.ds_nome_usuario');
		$select->joinLeft(array('vp'=>'vistorias_previas_temp'),'vp.id_endosso = p.id_endosso', array('vp.id as id_proposta_vistoria','vp.id_status'));
		$select->joinLeft(array('vis'=>'sistema.vistorias'),'vp.id_vistoria = vis.id ', false);
		$select->joinLeft(array('pb'=>'boletos_temp'),'pe.id_endosso = pb.id_endosso', false);
		
		$select->where("sst.ds_chave IN ('AGUARDANDO_ENVIO_SEG','AGUARDANDO_VISTORIA_PREVIA', 'APOLICE_EMITIDA', 'TRANSMITIDA_SEGURADORA', 'AGUARDANDO_EMISSAO')");

		$whereClause = array();
		if (is_array($where)) {
			foreach ($where as $clause) {
				if (is_array($clause)) {
					$field    = $clause['field'];
					$operator = $clause['operator'];
					$value    = $clause['value'];
					if($field == 'vp.id_status' || $field == 'pb.fl_pago') {
						$whereClause[] = "$field $operator $value";
					}else if($field == 'vp.id_status' && $value == 'null') {
						$whereClause[] = "$field $operator '$value'";
					}else if($field == 's.ds_chave'){
					    $fl_nao_encaminhada = true;
						$whereClause[] = "$field IN ('AGUARDANDO_ENVIO_SEG','AGUARDANDO_VISTORIA_PREVIA', 'APOLICE_EMITIDA', 'TRANSMITIDA_SEGURADORA', 'AGUARDANDO_EMISSAO')";
						$whereClause[] = "
                                            (
                                                SELECT
                                                    COUNT(*)
                                                FROM
                                                    seguro.propostas pr,
                                                    seguro.propostas_coberturas prc,
                                                    produto.produtos_coberturas pdc
                                                WHERE
                                                    pr.id_produto = pdc.id_produto AND
                                                    pr.id = prc.id_proposta AND
                                                    pdc.id_cobertura = prc.id_cobertura AND
                                                    pdc.fl_vistoria_previa = true AND
                                                    prc.id_proposta = p.id
                                            ) > 0
						";
					} else if ($field == 'fl_filtro_data_plantio') {
                        $fl_filtro_data_plantio = true;
					} else {
						$whereClause[] = "$field $operator $value";
					}

				} else {
					$whereClause[] = $clause;
				}
			}
		}

		if(count($whereClause) > 0) {
			$select .= ' and ' . implode(' and ', $whereClause);
		}

		if(!$fl_filtro_data_plantio and $fl_nao_encaminhada){
		    $select .= " and (sub.data_semeadura_validacao + 10) <= now()";
		}

		if(is_array($this->_order)) {
			$select .= " order by " . implode(' , ', $this->_order);
		} else {
			$select .= " order by " . $this->_order;
		}

		//echo "<pre>"; die($select);
		$Rs = $this->_db->fetchAll($select);
		return $Rs;
	}

	public function saveAgendamento($dados) {

		$sql = "SELECT id_vistoria FROM seguro.propostas_vistorias_previas WHERE id = {$dados['id_proposta_vistoria']}";
		$id_vistoria = $this->_db->fetchOne($sql);

		$sql = "SELECT id_agendamento FROM sistema.vistorias_agendamentos WHERE id_vistoria = $id_vistoria";
		$id_agendamento = $this->_db->fetchOne($sql);

		$ModelAgendamentos = new Sistema_Model_Agendamentos();
		$dados['id'] = $id_agendamento;

		$ModelAgendamentos->save($dados);

		$Row = $this->getRow($dados['id_proposta_vistoria']);

		if(!$Row) {
			return;
		}

		$sql = "SELECT
				s.id
				FROM
				sistema.status s INNER JOIN
				sistema.tipo_status t ON s.id_tipo_status = t.id
				WHERE
				t.ds_chave = 'VP' AND s.cd_status = 3";

		$status = $this->_db->fetchOne($sql);
		$Row->id_status = $status;

		return $Row->save();

	}


	public function countLaudosPrevia($idVistoria) {
		$select = $this->select();
		$select->setIntegrityCheck(false);
		$select->from(array('vpl'=>'seguro.vistorias_previas_laudos'),'count(id)');
		$select->where('id_vistoria = ? ', $idVistoria);

		return $this->_db->fetchOne($select);
	}

	public function getIdLaudo($idVistoria, $dtLaudo) {
		$select = $this->select();
		$select->setIntegrityCheck(false);
		$select->from(array('vpl'=>'seguro.vistorias_previas_laudos'),'id');
		$select->join(array('v'=>'sinistro.v_laudos_cobranca_previa'),'v.id_vistoria_previa_laudo = vpl.id',false);
		$select->where('vpl.id_vistoria = ? ', $idVistoria);
		$select->where('v.dt_vistoria = ? ', $dtLaudo);

		return $this->_db->fetchOne($select);
	}

	public function temLaudoDigitado($id_proposta){
		$select = $this->select()->setIntegrityCheck(false);
		$select->from(array("vp" => $this->_schema.".".$this->_name),'id');
		$select->where('vp.id_proposta = ?', $id_proposta);
		$select->where('vp.id_status IN (70,71)');

		$Rs = $this->getAdapter()->fetchAll($select);
		if(count($Rs)){
			return true;
		}

		return false;
	}

	public function temLaudoNaoTransmitido($id_proposta){

		$Safra = new Produto_Model_Safras();
		$schema = $Safra->getSafraModel($id_proposta);

		$select = $this->select()->setIntegrityCheck(false);
		$select->from(array("vp" => $this->_schema.".".$this->_name),'id');
		$select->join(array('lvp001'=>$schema.'.lvp001'),'lvp001.id_proposta_vistoria = vp.id',false);
		$select->where('vp.id_proposta = ?', $id_proposta);
		$select->where('lvp001.fl_transmitido = ?','false');

		$Rs = $this->getAdapter()->fetchRow($select);
		if(!$Rs){
			return false;
		}

		return true;

	}

    public function getEmpresaByVistoria($id) {

        $select = $this->select()->setIntegrityCheck(false);
        $select->from(array('pvp' => $this->_schema.'.'.$this->_name), false);
        $select->join(array('ve' => 'sistema.vistorias_empresas'), 've.id_vistoria = pvp.id_vistoria', false);
        $select->join(array('e' => 'sistema.empresas'), 'e.id = ve.id_empresa', 'e.ds_nome_fantasia');
        $select->where('pvp.id = ?', $id);

        $nome = $this->getAdapter()->fetchOne($select);
        return ($nome ? $nome : false);
    }

	public function updateVistoriaMobile($id_vistoria){
		$this->_db->query('update seguro.propostas_vistorias_previas set fl_sincronizado = true where id_vistoria = '. $id_vistoria);
		return true;
	}

	public function getAgendamentoVistoriaPreviaByProposta($idProposta)
	{
		$select = $this->select()->setIntegrityCheck(false);
		$select->from(array('pvp' => $this->_schema.'.'.$this->_name), array('pvp.id as id_vistoria_previa', 'pvp.id_vistoria', "to_char(pvp.dt_prazo_agendamento, 'DD/MM/YYYY') as dt_prazo_agendamento"));
		$select->joinLeft(array('va' => 'sistema.vistorias_agendamentos'), 'va.id_vistoria = pvp.id_vistoria', false);
		$select->joinLeft(array('a' => 'sistema.agendamentos'), 'va.id_agendamento = a.id', array('a.id as id_agendamento', "to_char(a.dt_agendamento, 'DD/MM/YYYY') as dt_agendamento"));
		$select->where('pvp.id_proposta = ?', $idProposta);

		$row = $this->getAdapter()->fetchRow($select);
        return $row;
	}

	public function getById($idVP) {
		
	}

	public function getDataConsulta($where = array()) {
		$sql = "
			SELECT p.id,
			       p.id_proposta_mae,
			       s.cd_status || ' - ' || s.ds_status as status,
			       prop.ds_nome_proponente,
			       prod.ds_nome_abreviado,
			       m.ds_nome_municipio || '/' || e.ds_sigla as municipio,
			       case when su.ds_nome_usuario <> '' then su.ds_nome_usuario else su_criacao.ds_nome_usuario end as digitador,
			       svp.id as status_vistoria_id,
			       svp.ds_status as status_vistoria,
			       sa.id as status_analise_id,
			       sa.ds_status as status_analise,
			       case 
			         when svp.id = 71 THEN (SELECT dt_transmissao 
			         	                      FROM regulacao.lvp001 
			         	                     WHERE lvp001.id_proposta_vistoria = pvp.id order by lvp001.id_proposta_vistoria desc limit 1
			         	                   )
			         when svp.id = 70 THEN (SELECT dt_agendamento 
			         						  FROM sistema.agendamentos ag 
			         						  JOIN sistema.vistorias_agendamentos va ON va.id_agendamento = ag.id
			         						  JOIN sistema.vistorias v ON v.id = va.id_vistoria
			         						 WHERE pvp.id_vistoria = v.id order by v.id desc limit 1
			     						   ) 
			         else NULL
			       end as data,
			       sve.id_empresa,
			       prod.id_safra,
			       pvp.id as id_proposta_vistoria
			  FROM seguro.propostas AS p
			  JOIN sistema.status AS s ON s.id = p.id_status
			  JOIN seguro.propostas_proponentes as prop ON prop.id_proposta = p.id
			  JOIN produto.produtos AS prod ON p.id_produto = prod.id
			  JOIN seguro.propostas_propriedades AS pp ON pp.id_proposta = p.id
			  JOIN sistema.municipios AS m ON m.id = pp.id_municipio 
			  JOIN sistema.estados AS e ON e.id = m.id_estado
			  JOIN seguro.propostas_vistorias_previas pvp ON pvp.id_proposta = p.id
			  JOIN sistema.status AS svp ON svp.id = pvp.id_status
			  JOIN sistema.status AS sa ON sa.id = pvp.id_status_analise
			  JOIN sistema.usuarios AS su_criacao ON su_criacao.id = p.id_usuario_criacao
			  LEFT JOIN sistema.prepostos sp ON sp.id_usuario = p.id_usuario_criacao
			  LEFT JOIN sistema.usuarios su ON su.id = sp.id_usuario
			  LEFT JOIN sistema.vistorias_empresas sve ON sve.id_vistoria = pvp.id_vistoria
 		";

 		if (!empty($where)) {
 			$sql .= "WHERE " . implode(" AND ", $where);
 		}

		$rs = $this->_db->fetchAll($sql);
		return $rs;
	}

    public function getVistoriasByProposta(int $idProposta)
    {
        $select = $this->select()->setIntegrityCheck(false);
        $select->from(['spvp' => "{$this->_schema}.{$this->_name}"]);
        $select->where('spvp.id_proposta = ?', $idProposta);

        return $this->fetchAll($select);
    }

	public function getIdByPropostaVistoria(int $idProposta, int $idVistoria) {
	    $sub1 = $this->select()->setIntegrityCheck(false)
		    ->from(['pr' => 'seguro.propostas'], 'id_endosso')
	    	    ->where('id = ?', $idProposta);
	    $sub2 = $this->select()->setIntegrityCheck(false)
		    ->from(['pe' => 'seguro.propostas_endosso'], 'id_proposta')
		    ->where('id_endosso = ('.$sub1.')')
	    	    ->where('fl_proposta_vigente = true');
	    $select = $this->select()->setIntegrityCheck(false)
            	    ->from(['spvp' => "{$this->_schema}.{$this->_name}"], 'id')
            ->where('spvp.id_proposta = ('.$sub2.')')
            ->where('spvp.id_vistoria = ?', $idVistoria); 
        return $this->fetchRow($select);
    }

    public function updateIdPropostaEndossada(int $idProposta, int $idPropostaEndossada) {
        $vistorias = $this->fetchAll('id_proposta = '. $idPropostaEndossada.' and id_status not in (71,226)')->toArray(); 

        if (count($vistorias) > 0) {
            foreach ($vistorias as $vistoria) {
                $this->update(
                    ['id_proposta' => $idProposta],
                    'id = ' . $vistoria['id']
                );
            }
        }
    }

	/**
	 * Retorna as vistorias de acordo com a proposta e os status informados.
	 * 
	 * @param int $idProposta
	 * @param array $idStatus
	 */
	public function getByPropostaStatus(int $idProposta, array $idsStatus) {
		$status = implode(',', $idsStatus);

		$select = $this->select()->setIntegrityCheck(false);
		$select->from(array("vp" => $this->_schema.".".$this->_name), ['id', 'id_status', 'id_vistoria']);
		$select->join(
			array("pr" => "seguro.propostas"),
			"pr.id = vp.id_proposta",
			'id_proposta_mae,
			cast(pg.id_ramo as varchar) || \'.\' ||
			cast(pd.id_seguradora as varchar) || \'.\' ||
			cast(pr.id_produto as varchar) || \'.\' ||
			cast(pr.id as varchar) || \'-\' ||
			cast(pr.nr_digito_verificador as varchar)
			as nr_proposta'
		);
		$select->join(array('pd'=>'produto.produtos'),'pr.id_produto = pd.id','ds_nome_produto','');
		$select->joinLeft(array('pg'=>'produto.produtos_geral'),'pd.id_produto_geral = pg.id','');
		$select->join(array("ve" => "sistema.vistorias_empresas"), "ve.id_vistoria = vp.id_vistoria", null);
		$select->join(array("e" => "sistema.empresas"), "e.id = ve.id_empresa", ["ds_email_responsavel", "ds_nome_responsavel"]);
		$select->joinLeft(array("va" => "sistema.vistorias_agendamentos"), "va.id_vistoria = vp.id_vistoria", null);
		$select->joinLeft(array("a" => "sistema.agendamentos"), "a.id = va.id_agendamento", "to_char(a.dt_agendamento, 'DD/MM/YYYY') as dt_agendamento");
		$select->where('vp.id_proposta = ?', $idProposta);
		$select->where("vp.id_status IN ({$status})");
		$select->order("a.dt_agendamento DESC, vp.id DESC");
		
		return $this->getAdapter()->fetchAll($select);
	}

	/**
	 * Retorna os dados da vistoria pelo ID da proposta e pelo ID da vistoria
	 *
	 * @param int $idProposta
	 * @param int $idVistoria
	 * @return array
	 */
	public function getByIdVistoria(int $idVistoria): array
	{
		$select = $this->select()->setIntegrityCheck(false);
		$select->from(array("vp" => $this->_schema.".".$this->_name));
		$select->where('vp.id_vistoria = ?', $idVistoria);

		$rs = $this->getAdapter()->fetchRow($select);
		return $rs === false ? [] : $rs;
	}

	/**
	 * Altera o status da análise da vistoria para "Concluída - sem alterações"
	 *
	 * @param int $idVistoria
	 * @return Zend_Db_Table_Row
	 */
	private function alterarStatusAnaliseConcluida(int $idVistoria): Zend_Db_Table_Row
	{
		$row = $this->getRow($idVistoria);

		if (empty($row['id'])) {
			throw new Exception("Vistoria {$idVistoria} não encontrada.");
		}
			
		$row['id_status_analise'] = self::ID_STATUS_VP_ANALISE_CONCLUIDA_SEM_ALT;

		if (!$row->save()) {
			throw new Exception("Erro ao alterar o status de análise da vistoria {$idVistoria}.");
		}

		return $row;
	}

	/**
	 * Inclui um registro de alteração de status de análise da vistoria
	 *
	 * @param Zend_Db_Table_Row $row
	 */
	private function incluirHistorico(Zend_Db_Table_Row $row): void
	{
		$modelVistoriasEmpresas = new Sistema_Model_VistoriasEmpresas();
		$idEmpresaVistoria = $modelVistoriasEmpresas->getEmpresaByVistoria($row['id_vistoria']);

		if (empty($idEmpresaVistoria)) {
			throw new Exception("Erro ao buscar a empresa da vistoria {$row['id_vistoria']}.");
		}

		$modelVistoriaPreviaHistorico = new Seguro_Model_VistoriaPreviaHistorico();
		$dados['id_proposta_vistoria'] = $row->id;
		$dados['id_status'] = $row->id_status;
		$dados['id_status_analise'] = self::ID_STATUS_VP_ANALISE_CONCLUIDA_SEM_ALT;
		$dados['id_empresa_historico'] = $idEmpresaVistoria;
		$dados['id_status_alteracao'] = $row->id_status_alteracao;
		
		if (!$modelVistoriaPreviaHistorico->save($dados)) {
			throw new Exception("Erro ao incluir o histórico de alteração da vistoria {$row['id_vistoria']}.");
		}
	}

	/**
	 * Percorre todos os documentos da vistoria e altera para "Liberado" (fl_fila_transmissao = false)
	 * todos os arquivos que são diferentes do tipo "FOTO" e que estejam
	 * como "Aguardando Liberação" (fl_fila_transmissao = true).
	 *
	 * @param int $idPropostaVistoria
	 * @param int $idVistoria
	 */
	private function liberarDocumentos(int $idPropostaVistoria, int $idVistoria): void
	{
		$modelVistoriaPreviaEmpresaArquivos = new Seguro_Model_Vistoriapreviaempresaarquivos();
		$arquivos = $modelVistoriaPreviaEmpresaArquivos->getArquivos($idPropostaVistoria);
		
		foreach ($arquivos as $arquivo) {
			if ($arquivo['id_tipo_arquivo_laudo_previa'] != Sistema_Model_TipoArquivoLaudoPrevia::TIPO_FOTO &&
				!$arquivo['fl_fila_transmissao']
			){
				try {
					$modelVistoriaPreviaEmpresaArquivos->transmiteArquivo($arquivo['id'],$arquivo['ds_nome_arquivo']);
				} catch (\Throwable $th) {
					throw new Exception("Não foi possível realizar a liberação do arquivo {$arquivo['ds_nome_arquivo']} da vistoria {$idVistoria}.");
				}
			}
		}
	}

	/**
	 * Cadastra uma observação na proposta informado que a digitação de sinistro foi liberada
	 *
	 * @param int $idProposta
	 */
	private function cadastrarObservacao(int $idProposta): void
	{
		$modelPropostasObservacoes = new Seguro_Model_PropostasObservacoes();
		$dados = [
			'id_proposta' => $idProposta,
			'ds_observacao' => 'Digitação de Sinistro Liberada.'
		];
		
		if (!$modelPropostasObservacoes->save($dados)) {
			throw new Exception("Erro ao incluir a observação da proposta {$idProposta}.");
		}
	}

	/**
	 * Atualiza o status de análise para "Concluída - sem alterações", inclui o histórico de alteração do status,
	 * libera os documentos que estão como "Aguardando Liberação" e cadastra uma observação pra proposta.
	 *
	 * @param int $idVistoria
	 */
	public function concluirAnalise(int $idVistoria): void
	{
		$row = $this->alterarStatusAnaliseConcluida($idVistoria);
		$this->incluirHistorico($row);
		$this->liberarDocumentos($row['id'], $idVistoria);
		$this->cadastrarObservacao($row['id_proposta']);
	}
}
