<?php

namespace App\DAO;

use App\DAO\DAO;
use App\DAO\DAOResponse\DAOResponse;
use App\DAO\DAOResponse\DAOResponseInterface;
use App\ViewModels\ProdutoServico\ProdutoChangeStatusViewModel\ProdutoChangeStatusViewModel;
use App\ViewModels\ProdutoServico\ProdutoRegistrationViewModel\ProdutoRegistrationViewModel;
use App\Services\LogService;

class ProdutoServicoDAO extends DAO {

	public function registerProduto(ProdutoRegistrationViewModel $produtoRegistration_vm): DAOResponse {

		$daoResponse = new DAOResponse();

		$sql = <<<SQL
			insert into produto_servico 
				(nome, descricao, id_unidade, id_tipo, id_status, criado_por, data_criacao, hora_criacao, valor) values
				(:nome:,:descricao:,:unidade_id:,:tipo_id:,:status_id:,:usuario_id:,:data_c:,:hora_c:,:valor:)
			
		SQL;

		$binds = [ 
			'nome' => $produtoRegistration_vm->getNome(),
			'descricao' => $produtoRegistration_vm->getDescricao(),
			'unidade_id' => $produtoRegistration_vm->getIdUnidade(),
			'tipo_id' => $produtoRegistration_vm->getIdTipo(),
			'status_id' => $produtoRegistration_vm->getIdStatus(),
			'usuario_id' => $produtoRegistration_vm->getCriadoPor(),
			'data_c' => $produtoRegistration_vm->getDataCriacao(),
			'hora_c' => $produtoRegistration_vm->getHoraCriacao(),
			'valor' => $produtoRegistration_vm->getValor()
		];

		$conn = db_connect();
		$numrows = $conn->query( $sql, $binds )->numRows;
		$errors = $conn->error();

		if ($errors ['code'] != 0) {
			$daoResponse->setStatus( DAOResponseInterface::DATABASE_CONNECTION_ERROR );
			$daoResponse->setErrors( $errors );
			$daoResponse->setData( [ ] );
		} else {
			$affectrows = $conn->affectedRows();
			if ($affectrows == 0) {
				$daoResponse->setStatus( DAOResponseInterface::INSUFFICIENT_DATA );
				$daoResponse->setData( [ ] );
			} else {
				$newid = $conn->insertID();
				$daoResponse->setStatus( DAOResponseInterface::SUCESS );
				$daoResponse->setData( [ 
					'id_produto' => $newid
				] );
			}
		}

		return $daoResponse;

	}

	public function isExistProdutoToUnidadeId(ProdutoRegistrationViewModel $produtoRegistration_vm): DAOResponse {

		$daoResponse = new DAOResponse();

		$sql = <<<SQL
			select count(*) total from produto_servico 
			where 
				id_unidade = :unidade_id:
				and nome = :nome_produto:
		SQL;
		$binds = [ 
			'unidade_id' => $produtoRegistration_vm->getIdUnidade(),
			'nome_produto' => trim( $produtoRegistration_vm->getNome() )
		];

		$conn = db_connect();
		$result = $conn->query( $sql, $binds )
			->getResultArray();
		$errors = $conn->error();

		if ($errors ['code'] != 0) {
			$daoResponse->setStatus( DAOResponseInterface::DATABASE_CONNECTION_ERROR );
			$daoResponse->setErrors( $errors );
			$daoResponse->setData( [ ] );
		} else {
			$resultado = $result [0];
			if (intval( $resultado ['total'] ) == 0) {
				$daoResponse->setStatus( DAOResponseInterface::RECORD_NOT_FOUND );
				$daoResponse->setData( [ ] );
			} else {
				$daoResponse->setStatus( DAOResponseInterface::SUCESS );
				$daoResponse->setData( $resultado );
			}
		}

		return $daoResponse;

	}

	public function changeStatusProduto(ProdutoChangeStatusViewModel $produtoChangeStatus_vm): DAOResponse {

		$daoResponse = new DAOResponse();

		$sql = <<<SQL
			update produto_servico
				set id_status = :status_id: , alterado_por = :usuario_id:,
					data_alteracao = :data_a:, hora_alteracao = :hora_a:
				where id = :id_produto:
		SQL;

		$binds = [ 
			'id_produto' => $produtoChangeStatus_vm->getId(),
			'status_id' => $produtoChangeStatus_vm->getIdStatus(),
			'usuario_id' => $produtoChangeStatus_vm->getAlteradoPor(),
			'data_a' => $produtoChangeStatus_vm->getDataAlteracao(),
			'hora_a' => $produtoChangeStatus_vm->getHoraAlteracao()
		];

		$conn = db_connect();
		$numrows = $conn->query( $sql, $binds )->numRows;
		$errors = $conn->error();

		if ($errors ['code'] != 0) {
			$daoResponse->setStatus( DAOResponseInterface::DATABASE_CONNECTION_ERROR );
			$daoResponse->setErrors( $errors );
			$daoResponse->setData( [ ] );
			log_message( "ERROR", json_encode( $errors ) );
		} else {
			$affectrows = $conn->affectedRows();
			if ($affectrows == 0) {
				$daoResponse->setStatus( DAOResponseInterface::INSUFFICIENT_DATA );
				$daoResponse->setData( [ ] );
			} else {
				$daoResponse->setStatus( DAOResponseInterface::SUCESS );
				$daoResponse->setData( [ ] );
			}
		}

		return $daoResponse;

	}

	public function getProdutos(): DAOResponse {

		$daoResponse = new DAOResponse();

		$sql = <<<SQL
			SELECT DISTINCT
				ps.id , ps.nome , ps.descricao , ps.id_unidade, u.descricao as unidade ,
				l.id as id_loja , pj.nome_fantasia ,ps.id_tipo, tps.nome as tipo_nome,
				tps.descricao as tipo_descricao , ps.id_status, pss.descricao as produto_status,
				ps.criado_por, pf.nome as criado_por , ps.data_criacao , ps.hora_criacao , ps.valor
			FROM
				produto_servico ps, tipo_produto_servico tps , produto_servico_status pss ,
				loja l, unidade u, pessoa_fisica pf ,pessoa_juridica pj  , usuario us
			WHERE
				ps.id_unidade = u.id
				and ps.id_unidade = l.id_unidade
				and ps.id_tipo = tps.id
				and ps.id_status = pss.id
				and ps.criado_por = us.id
				and us.id_pessoa = pf.id_pessoa
				and u.id_pessoa_juridica  = pj.id
			ORDER BY
				ps.id_unidade asc, ps.id asc
		SQL;
		$binds = [ ];

		$conn = db_connect();
		$result = $conn->query( $sql, $binds )
			->getResultArray();
		$errors = $conn->error();

		if ($errors ['code'] != 0) {
			$daoResponse->setStatus( DAOResponseInterface::DATABASE_CONNECTION_ERROR );
			$daoResponse->setErrors( $errors );
			$daoResponse->setData( [ ] );
		} else {
			if (count( $result ) == 0) {
				$daoResponse->setStatus( DAOResponseInterface::RECORD_NOT_FOUND );
				$daoResponse->setData( [ ] );
			} else {
				$daoResponse->setStatus( DAOResponseInterface::SUCESS );
				$daoResponse->setData( [ 
					'produtos' => $result
				] );
			}
		}

		return $daoResponse;

	}

	public function getProdutosLojaId(int $id_loja, int $id_status_produto): DAOResponse {

		$daoResponse = new DAOResponse();

		$sql = "";
		$binds = [ ];

		if ($id_status_produto == 0) {
			$sql = <<<SQL
				SELECT DISTINCT
					ps.id , ps.nome , ps.descricao , ps.id_unidade, u.descricao as unidade ,
					lp.id as id_loja_produto, lp.id_status as id_loja_produto_status,
					lps.descricao  as loja_produto_status,
					l.id as id_loja , pj.nome_fantasia ,ps.id_tipo, tps.nome as tipo_nome,
					tps.descricao as tipo_descricao , ps.id_status as id_produto_status, 
					pss.descricao as produto_status, ps.criado_por, pf.nome as criado_por , 
					ps.data_criacao , ps.hora_criacao , ps.valor
				FROM
					produto_servico ps, tipo_produto_servico tps , produto_servico_status pss ,
					loja l, loja_produto lp , loja_produto_status lps, unidade u,
					pessoa_fisica pf ,pessoa_juridica pj  , usuario us
				WHERE
					l.id = :loja_id:
					and l.id = lp.id_loja
					and l.id_unidade = ps.id_unidade
					and lp.id_status = lps.id
					and lp.id_produto = ps.id
					and ps.id_unidade = u.id
					and ps.id_tipo = tps.id
					and ps.id_status = pss.id
					and ps.criado_por = us.id
					and us.id_pessoa = pf.id_pessoa
					and u.id_pessoa_juridica  = pj.id
				ORDER BY
					ps.nome ASC, ps.id_unidade ASC, ps.id ASC
			SQL;
			$binds = [ 
				'loja_id' => $id_loja
			];
		} else {
			$sql = <<<SQL
				SELECT DISTINCT
					ps.id , ps.nome , ps.descricao , ps.id_unidade, u.descricao as unidade ,
					lp.id as id_loja_produto, lp.id_status as id_loja_produto_status,
					lps.descricao  as loja_produto_status,
					l.id as id_loja , pj.nome_fantasia ,ps.id_tipo, tps.nome as tipo_nome,
					tps.descricao as tipo_descricao , ps.id_status as id_produto_status, 
					pss.descricao as produto_status, ps.criado_por, pf.nome as criado_por , 
					ps.data_criacao , ps.hora_criacao , ps.valor
				FROM
					produto_servico ps, tipo_produto_servico tps , produto_servico_status pss ,
					loja l, loja_produto lp , loja_produto_status lps, unidade u,
					pessoa_fisica pf ,pessoa_juridica pj  , usuario us
				WHERE
					l.id = :loja_id:
					and l.id = lp.id_loja
					and l.id_unidade = ps.id_unidade
					and lp.id_status = lps.id
					and lp.id_produto = ps.id
					and ps.id_unidade = u.id
					and ps.id_status = :status_produto_id: 
					and ps.id_status = pss.id
					and ps.id_tipo = tps.id
					and ps.criado_por = us.id
					and us.id_pessoa = pf.id_pessoa
					and u.id_pessoa_juridica  = pj.id
				ORDER BY
					ps.nome ASC, ps.id_unidade ASC, ps.id ASC
			SQL;
			$binds = [ 
				'loja_id' => $id_loja,
				'status_produto_id' => $id_status_produto
			];
		}

		$conn = db_connect();
		$result = $conn->query( $sql, $binds )
			->getResultArray();
		$errors = $conn->error();

		if ($errors ['code'] != 0) {
			$daoResponse->setStatus( DAOResponseInterface::DATABASE_CONNECTION_ERROR );
			$daoResponse->setErrors( $errors );
			$daoResponse->setData( [ ] );
		} else {
			if (count( $result ) == 0) {
				$daoResponse->setStatus( DAOResponseInterface::RECORD_NOT_FOUND );
				$daoResponse->setData( [ ] );
			} else {
				$daoResponse->setStatus( DAOResponseInterface::SUCESS );
				$daoResponse->setData( [ 
					'produtos' => $result
				] );
			}
		}

		return $daoResponse;

	}

	public function getProdutosUnidadeId(int $id_unidade): DAOResponse {

		$daoResponse = new DAOResponse();

		$sql = <<<SQL
			SELECT DISTINCT
				ps.id , ps.nome , ps.descricao , ps.id_unidade, u.descricao as unidade ,
				l.id as id_loja , pj.nome_fantasia ,ps.id_tipo, tps.nome as tipo_nome,
				tps.descricao as tipo_descricao , ps.id_status, pss.descricao as produto_status,
				ps.criado_por, pf.nome as criado_por , ps.data_criacao , ps.hora_criacao , ps.valor
			FROM
				produto_servico ps, tipo_produto_servico tps , produto_servico_status pss ,
				loja l, unidade u, pessoa_fisica pf ,pessoa_juridica pj  , usuario us
			WHERE
				ps.id_unidade = :unidade_id:
				and ps.id_unidade = l.id_unidade				
				and ps.id_unidade = u.id
				and ps.id_tipo = tps.id
				and ps.id_status = pss.id
				and ps.criado_por = us.id
				and us.id_pessoa = pf.id_pessoa
				and u.id_pessoa_juridica  = pj.id
			ORDER BY
				ps.id_unidade asc, ps.id asc
		SQL;
		$binds = [ 
			'unidade_id' => $id_unidade
		];

		$conn = db_connect();
		$result = $conn->query( $sql, $binds )
			->getResultArray();
		$errors = $conn->error();

		if ($errors ['code'] != 0) {
			$daoResponse->setStatus( DAOResponseInterface::DATABASE_CONNECTION_ERROR );
			$daoResponse->setErrors( $errors );
			$daoResponse->setData( [ ] );
		} else {
			if (count( $result ) == 0) {
				$daoResponse->setStatus( DAOResponseInterface::RECORD_NOT_FOUND );
				$daoResponse->setData( [ ] );
			} else {
				$daoResponse->setStatus( DAOResponseInterface::SUCESS );
				$daoResponse->setData( [ 
					'produtos' => $result
				] );
			}
		}

		return $daoResponse;

	}

	public function getProdutosUnidadeIdWithoutLoja(int $id_unidade, int $id_status): DAOResponse {

		$daoResponse = new DAOResponse();

		$sql = "";
		$binds = [ ];

		if ($id_status == 0) {
			$sql = <<<SQL
				SELECT DISTINCT
					ps.id , ps.nome , ps.descricao , ps.id_unidade, u.descricao as unidade ,
					ps.id_tipo, tps.nome as tipo_nome, tps.descricao as tipo_descricao ,
					ps.id_status, pss.descricao as produto_status,	ps.criado_por,
					pf.nome as criado_por , ps.data_criacao , ps.hora_criacao , ps.valor
				FROM
					produto_servico ps, tipo_produto_servico tps , produto_servico_status pss ,
					unidade u, pessoa_fisica pf ,pessoa_juridica pj  , usuario us
				WHERE
					ps.id_unidade = :unidade_id:				
					and ps.id not in ( select distinct  psc.id from loja l , loja_produto lp, produto_servico psc
							where l.id_unidade = :unidade_id: and l.id = lp.id_loja and l.id_unidade = psc.id_unidade
							and lp.id_produto = psc.id)
					and ps.id_unidade = u.id
					and ps.id_tipo = tps.id
					and ps.id_status = pss.id
					and ps.criado_por = us.id
					and us.id_pessoa = pf.id_pessoa
					and u.id_pessoa_juridica  = pj.id
				ORDER BY
					ps.id_unidade asc, ps.nome asc
			SQL;
			$binds = [ 
				'unidade_id' => $id_unidade
			];
		} else {
			$sql = <<<SQL
				SELECT DISTINCT
					ps.id , ps.nome , ps.descricao , ps.id_unidade, u.descricao as unidade ,
					ps.id_tipo, tps.nome as tipo_nome, tps.descricao as tipo_descricao ,
					ps.id_status, pss.descricao as produto_status,	ps.criado_por,
					pf.nome as criado_por , ps.data_criacao , ps.hora_criacao , ps.valor
				FROM
					produto_servico ps, tipo_produto_servico tps , produto_servico_status pss ,
					unidade u, pessoa_fisica pf ,pessoa_juridica pj  , usuario us
				WHERE
					ps.id_unidade = :unidade_id:
					and ps.id_status = :status_id:
					and ps.id not in ( select distinct  psc.id from loja l , loja_produto lp, produto_servico psc
							where l.id_unidade = :unidade_id: and l.id = lp.id_loja and l.id_unidade = psc.id_unidade 
							and lp.id_produto = psc.id)
					and ps.id_unidade = u.id
					and ps.id_tipo = tps.id
					and ps.id_status = pss.id
					and ps.criado_por = us.id
					and us.id_pessoa = pf.id_pessoa
					and u.id_pessoa_juridica  = pj.id
				ORDER BY
					ps.id_unidade asc, ps.nome asc
			SQL;
			$binds = [ 
				'unidade_id' => $id_unidade,
				'status_id' => $id_status
			];
		}

		$conn = db_connect();
		$result = $conn->query( $sql, $binds )
			->getResultArray();
		$errors = $conn->error();

		if ($errors ['code'] != 0) {
			$daoResponse->setStatus( DAOResponseInterface::DATABASE_CONNECTION_ERROR );
			$daoResponse->setErrors( $errors );
			$daoResponse->setData( [ ] );
		} else {
			if (count( $result ) == 0) {
				$daoResponse->setStatus( DAOResponseInterface::RECORD_NOT_FOUND );
				$daoResponse->setData( [ ] );
			} else {
				$daoResponse->setStatus( DAOResponseInterface::SUCESS );
				$daoResponse->setData( [ 
					'produtos' => $result
				] );
			}
		}

		return $daoResponse;

	}

	public function getProdutoFromlojaProdutoId(int $idcompra, int $idlojaproduto): DAoResponse {

		$daoResponse = new DAOResponse();

		$sql = <<<SQL
			select
				lci.id , lci.id_loja_compra , lci.id_loja_produto,
				lp.id_status as loja_produto_status_id, ps.voucher ,
				ps.id_tipo_voucher
			from
				loja_compra_item lci, loja_produto lp ,
				produto_servico ps
			where
				lci.id_loja_compra = :loja_compra_id:
				and lci.id_loja_produto = :loja_produto_id:
				and lci.id_loja_produto = lp.id
				and lp.id_produto = ps.id
		SQL;

		$binds = [ 
			'loja_compra_id' => $idcompra,
			'loja_produto_id' => $idlojaproduto
		];

		$conn = db_connect();
		$result = $conn->query( $sql, $binds )
			->getResultArray();
		$errors = $conn->error();

		if ($errors ['code'] != 0) {
			$daoResponse->setStatus( DAOResponseInterface::DATABASE_CONNECTION_ERROR );
			$daoResponse->setErrors( $errors );
			$daoResponse->setData( [ ] );
		} else {
			if (count( $result ) == 0) {
				$daoResponse->setStatus( DAOResponseInterface::RECORD_NOT_FOUND );
				$daoResponse->setData( [ ] );
			} else {
				$daoResponse->setStatus( DAOResponseInterface::SUCESS );
				$daoResponse->setData( $result [0] );
			}
		}

		return $daoResponse;

	}

}

