<?php
namespace Incoviba\old\Venta;

use Incoviba\Common\Alias\OldModel as Model;
use Carbon\Carbon;
//use Incoviba\old\Proyecto\Agente;
use Incoviba\old\Proyecto\ProyectoAgente;

/**
 *
 * @property int id
 * @property Propietario propietario
 * @property Propiedad propiedad
 * @property Pie pie
 * @property BonoPie bono_pie
 * @property Credito credito
 * @property Escritura escritura
 * @property Subsidio subsidio
 * @property date escriturado
 * @property Entrega entrega
 * @property date entregado
 * @property date fecha
 * @property float valor_uf
 * @property int estado
 * @property date fecha_ingreso
 * @property int avalchile
 * @property ProyectoAgente agente
 * @property float uf
 * @property boolean relacionado
 * @property Promocion promocion
 * @property Pago resciliacion
 *
 */
class Venta extends Model
{
	 protected $saldo;
	 protected $uf;
	 protected $anticipo;
	 protected $pagado;
	 protected $comision;
	 protected $valor_neto;
	 protected $promociones;
	 protected $valor_corredora;

	 public function propietario()
	 {
	 	return $this->belongs_to(Propietario::class, 'propietario', 'rut')->findOne();
	 }
	 public function propiedad()
	 {
	 	return $this->belongs_to(Propiedad::class, 'propiedad')->findOne();
	 }
	 public function bonoPie()
	 {
	 	$bono = $this->belongs_to(BonoPie::class, 'bono_pie');
	 	if ($bono) {
	 		return $bono->findOne();
	 	}
	 	return null;
	 }
	 public function pie()
	 {
	 	$pie = $this->belongs_to(Pie::class, 'pie');
	 	if ($pie) {
	 		return $pie->findOne();
	 	}
	 	return null;
	 }
	 public function entrega()
	 {
	 	if ($this->entrega != '0') {
	 		return $this->belongs_to(Entrega::class, 'entrega')->findOne();
	 	}
	 	return null;
	 }
	 public function fecha()
	 {
	 	return Carbon::parse($this->fecha, new \DateTimeZone(config('app.timezone')));
	 }
	 public function proyecto()
	 {
	 	return $this->propiedad()->unidad()->proyecto();
	 }
	 public function unidad()
	 {
	 	return $this->propiedad()->unidad();
	 }
	 public function agente()
	 {
	 	$agente = $this->belongs_to(ProyectoAgente::class, 'agente');
	 	if ($agente) {
	 		return $agente->findOne();
	 	}
	 	return null;
	 }
	 public function comision()
	 {
		 if (!isset($this->comision)) {
			 $pa = $this->agente();
			 if ($pa and $pa->agente()->tipo == 19) {
				 $this->comision = $pa->comision / 100;
			 } else {
				 $this->comision = 0;
			 }
		 }
		 return $this->comision;
	 }
	 public function valorComision()
	 {
	 	$bono_pie = $this->bonoPie();
	 	if ($this->bono_pie != 0) {
	 		$bono_pie = $bono_pie->pago()->valor('ufs');
	 	} else {
	 		$bono_pie = 0;
	 	}
	 	return ($this->valor_uf - $bono_pie) * $this->comision();
	 }
	 protected $superficie_departamentos;
	 public function superficie() {
		 if ($this->superficie_departamentos == null) {
			 $this->superficie_departamentos = array_reduce($this->propiedad()->departamentos(), function($sum, $item) {
				 return $sum + $item->m2();
			 });
		 }
		 return $this->superficie_departamentos;
	 }
	 protected $valor_departamentos;
	 public function valorDepartamentos() {
		 if ($this->valor_departamentos == null) {
			 $fecha = $this->fecha();
			 $this->valor_departamentos = array_reduce($this->propiedad()->departamentos(), function($sum, $item) use ($fecha) {
				 return $sum + (isset($item->precio($fecha)->valor)) ? $item->precio($fecha)->valor : 0;
			 });
		 }
		 return $this->valor_departamentos;
	 }
	 protected $valor_unidades;
	 public function valorUnidades() {
		 if ($this->valor_unidades == null) {
			 $fecha = $this->fecha();
			 $this->valor_unidades = array_reduce($this->propiedad()->unidades(), function($sum, $item) use ($fecha) {
				 return $sum + (isset($item->unidad()->precio($fecha)->valor)) ? $item->unidad()->precio($fecha)->valor : 0;
			 });
		 }
		 return $this->valor_unidades;
	 }
	 public function valorEstacionamientos()
	 {
		 $estacionamientos = $this->propiedad()->estacionamientos();
		 $sum = 0;
		 foreach ($estacionamientos as $estacionamiento) {
			 $sum += (isset($estacionamiento->precio($this->fecha())->valor)) ? $estacionamiento->precio($this->fecha())->valor : 0;
		 }
		 return $sum;
	 }
	 public function valorBodegas()
	 {
	 	$bodegas = $this->propiedad()->bodegas();
	 	$sum = 0;
	 	foreach ($bodegas as $bodega) {
	 		$sum += (isset($bodega->precio($this->fecha())->valor)) ? $bodega->precio($this->fecha())->valor : 0;
	 	}
	 	return $sum;
	 }
	 public function valorEstacionamientosYBodegas()
	 {
		 return $this->valorEstacionamientos() + $this->valorBodegas();
	 }
	 public function valorCorredora()
	 {
		 if ($this->valor_corredora == null) {
			 $bono_pie = $this->bonoPie();
 		 	 if ($this->bono_pie != 0) {
 				 $bono_pie = $bono_pie->pago()->valor('ufs');
 		 	 } else {
 		 	 	$bono_pie = 0;
 		 	 }
			 $promos = 0;
	 		 $ps = $this->promociones();
	 		 if (count($ps) > 0) {
	 			 foreach ($ps as $promo) {
	 				 $promos += $promo->valor;
	 			 }
	 		 }
			 $this->valor_corredora = $this->valor_uf - $bono_pie - $promos;
		 }
		 return $this->valor_corredora;
	 }
	 public function valorFinal()
	 {
		 if (!isset($this->valor_neto)) {
		 	$comision = $this->valorComision();
		 	$bono_pie = $this->bonoPie();
		 	if ($this->bono_pie != 0) {
				$bono_pie = $bono_pie->pago()->valor('ufs');
		 	} else {
		 		$bono_pie = 0;
		 	}
		 	$ests = $this->valorEstacionamientos();
		 	$bods = $this->valorBodegas();
			$promos = 0;
			$ps = $this->promociones();
			if (count($ps) > 0) {
				foreach ($ps as $promo) {
					$promos += $promo->valor;
				}
			}
		 	$this->valor_neto = $this->valor_uf - $bono_pie - $comision - $ests - $bods - $promos;
		}
		return $this->valor_neto;
	 }
	 public function uf_m2()
	 {
		 $m2 = array_reduce($this->propiedad()->departamentos(), function($sum, $item) {
			 return $sum + $item->m2();
		 });
		 return $this->valorFinal() / $m2;
	 }
	 public function escritura()
	 {
	 	$escritura = $this->belongs_to(Escritura::class, 'escritura');
	 	if ($escritura) {
	 		return $escritura->findOne();
	 	}
	 	return null;
	 }
	 public function credito()
	 {
	 	$credito = $this->belongs_to(Credito::class, 'credito');
	 	if ($credito) {
	 		return $credito->findOne();
	 	}
	 	return null;
	 }
	public function comentarios()
	{
		return $this->has_many(Comentario::class, 'venta')->findMany();
	}
	public function subsidio()
	{
		$subsidio = $this->belongs_to(Subsidio::class, 'subsidio');
		if ($subsidio) {
			return $subsidio->findOne();
		}
		return null;
	}

	public function resciliacion()
	{
		$res = $this->belongs_to(Pago::class, 'resciliacion');
		if ($res) {
			return $res->findOne();
		}
		return null;
	}
	public function postventas()
	{
		$postventas = $this->has_many(\Incoviba\nuevo\Venta\Postventa::class, 'venta_id');
		if ($postventas) {
			return $postventas->findMany();
		}
		return null;
	}
	public function promociones()
	{
		if ($this->promociones == null) {
			$pvs = model(PromocionVenta::class)->where('venta', $this->id)->findMany();
			$this->promociones = $pvs;
		}
		return $this->promociones;
	}
	public function devolucion()
	{
		$devolucion = $this->belongsTo(Pago::class, 'devolucion');
		if ($devolucion) {
			return $devolucion->findOne();
		}
		return null;
	}
	public function anticipo($tipo = 'ufs')
	{
		if (!isset($this->anticipo[$tipo])) {
			$anticipo = 0;
			if ($this->pie != 0) {
				if ($tipo == 'ufs') {
					$anticipo += $this->pieReajustado($tipo);
				} else {
					$anticipo += $this->pie()->valorPagado($tipo);
				}
				if ($this->pie()->reajuste != 0) {
					$anticipo += $this->pie()->reajuste()->valor($tipo);
				}
			}
			if ($this->escritura != 0) {
				$anticipo += $this->escritura()->pago()->valor($tipo);
			}
			if ($this->saldo('ufs') > 0) {
				$anticipo -= $this->saldo($tipo);
			}
			$this->anticipo[$tipo] = $anticipo;
		}

		return $this->anticipo[$tipo];
	}
	public function saldo($tipo = 'ufs')
	{
		if (!isset($this->saldo[$tipo])) {
			if ($tipo == 'pesos') {
				$this->saldo[$tipo] = $this->saldo() * $this->uf();
				return $this->saldo[$tipo];
			}
			$saldo = $this->valor($tipo);
			if ($this->bono_pie != 0) {
				$saldo -= $this->bonoPie()->pago()->valor($tipo);
			}
			if ($this->pie != 0) {
				$saldo -= $this->pie()->valorPagado($tipo);
				if ($this->pie()->reajuste != 0) {
					$saldo -= $this->pie()->reajuste()->valor($tipo);
				}
			}
			if ($this->escritura != 0) {
				$saldo -= $this->escritura()->pago()->valor($tipo);
			}
			if ($this->subsidio != 0) {
				$saldo -= $this->subsidio()->total($tipo);
			}
			if ($this->credito != 0) {
				$saldo -= $this->credito()->pago()->valor($tipo);
			}
			if ($this->devolucion) {
				$saldo += $this->devolucion()->valor($tipo);
			}
			if ($this->resciliacion) {
				$saldo += $this->resciliacion()->valor($tipo);
			}
			$this->saldo[$tipo] = -$saldo;
		}

		return $this->saldo[$tipo];
	}
	public function valor($tipo = 'ufs')
	{
		if ($tipo == 'ufs') {
			return $this->valor_uf;
		}
		return $this->valor_uf * $this->uf();
	}
	protected $valores;
	public function valorPagado($tipo = 'ufs')
	{
		if ($this->valores == null or !isset($this->valores->pagado->ufs)) {
			$valores = [];
			if (isset($this->valores)) {
				$valores = (array) $valores;
			}
			$valores['pagado'] = (object) ['ufs' => 0, 'pesos' => 0];
			if ($this->pie()) {
				$valores['pagado']->ufs = $this->pie()->valorPagado();
				$valores['pagado']->pesos = $this->pie()->valorPagado('pesos');
			}
			$this->valores = (object) $valores;
		}
		return $this->valores->pagado->{$tipo};
	}
	public function valorAbonado($tipo = 'ufs')
	{
		if ($this->valores == null or !isset($this->valores->abonado->{$tipo})) {
			$valores = [];
			if (isset($this->valores)) {
				$valores = (array) $valores;
			}
			$valores['abonado'] = (object) ['ufs' => 0, 'pesos' => 0];
			if ($this->pie()) {
				$valores['abonado']->ufs = $this->pie()->valorAbonado();
				$valores['abonado']->pesos = $this->pie()->valorAbonado('pesos');
			}
			$this->valores = (object) $valores;
		}
		return $this->valores->abonado->{$tipo};
	}
	public function pagado($tipo = 'ufs')
	{
		if (!isset($this->pagado[$tipo])) {
			if (abs($this->saldo()) / $this->valor() > 0.01 or $tipo == 'pesos') {
				$total = 0;
				$total += $this->anticipo($tipo);

				if ($this->subsidio != 0) {
					$total += $this->subsidio()->total($tipo);
				}
				if ($this->credito != 0) {
					$total += $this->credito()->pago()->valor($tipo);
				}
				if ($this->devolucion) {
					$total -= $this->devolucion()->valor($tipo);
				}
				if ($this->resciliacion) {
					$total -= $this->resciliacion()->valor($tipo);
				}

				$this->pagado[$tipo] = $total;
			} else {
				$this->pagado[$tipo] = $this->valor($tipo);
			}
		}
		return $this->pagado[$tipo];
	}
	public function pieReajustado($tipo = 'ufs')
	{
		if (abs($this->saldo()) / $this->valor() > 0.01) {
			return $this->pie()->valorPagado($tipo);
		}
		$valor = $this->pie()->valorPagado($tipo) - $this->saldo($tipo);
		return $valor;
	}
	public function uf()
	{
		if ($this->uf == null) {
			$f = $this->fecha();
			$uf = uf($f);
			if ($uf == null) {
				return 1;
			}
			$this->uf = $uf->uf->value;
		}

		return $this->uf;
	}
	public function pagos($estado = 0)
	{
		$results = [];
		if ($this->pie != 0) {
			$results = array_merge($results, $this->pie()->pagos($estado));
		}
		if ($this->escritura != 0 and $this->escritura()->pago() and $this->escritura()->pago()->estado()->estado == $estado) {
			$results []= $this->escritura()->pago();
		}
		if ($this->credito != 0 and $this->credito()->pago()->estado()->estado == $estado) {
			$results []= $this->credito()->pago();
		}
		if ($this->subsidio != 0 and $this->subsidio()->pago()->estado()->estado == $estado) {
			$results []= $this->subsidio()->pago();
		}

		usort($results, function($a, $b) {
			return $a->estado()->fecha()->diffInDays($b->estado()->fecha(), false);
		});
		return $results;
	}
	public function new()
	{
		parent::save();
		$tipo = model(TipoEstadoVenta::class)->where('descripcion', 'vigente')->findOne();
		$data = [
			'venta' => $this->id,
			'estado' => $tipo->id,
			'fecha' => $this->fecha
		];
		$estado = model(EstadoVenta::class)->create($data);
		$estado->save();
	}
	public function estados()
	{
		return $this->hasMany(EstadoVenta::class, 'venta')->findMany();
	}
	public function estado($estado = null)
	{
		if ($estado == null) {
			return model(EstadoVenta::class)
				->select('estado_venta.*')
				->rawJoin('JOIN (SELECT venta, MAX(id) AS id FROM estado_venta GROUP BY venta)', ['estado_venta.id', '=', 'e0.id'], 'e0')
				->where('estado_venta.venta', $this->id)
				->findOne();
		}
		return model(EstadoVenta::class)
			->select('estado_venta.*')
			->join('tipo_estado_venta', ['tipo_estado_venta.id', '=', 'estado_venta.estado'])
			->where('estado_venta.venta', $this->id)
			->where('tipo_estado_venta.descripcion', $estado)
			->orderByDesc('estado_venta.fecha')
			->findOne();
	}
	public function firmar(Carbon $fecha)
	{
		$estado = $this->estado();
		if ($estado->tipo()->descripcion == 'firmado por inmobiliaria') {
			return true;
		}
		$tipo = model(TipoEstadoVenta::class)->where('descripcion', 'firmado por inmobiliaria')->findOne();
		$data = [
			'venta' => $this->id,
			'estado' => $tipo->id,
			'fecha' => $fecha->format('Y-m-d')
		];
		$estado = model(EstadoVenta::class)->create($data)->save();
		return true;
	}
	public function archivar(Carbon $fecha)
	{
		$estado = $this->estado();
		if ($estado->estado()->tipo()->descripcion == 'archivado') {
			return true;
		}
		$tipo = model(TipoEstadoVenta::class)->where('descripcion', 'archivado')->findOne();
		$data = [
			'venta' => $this->id,
			'estado' => $tipo->id,
			'fecha' => $fecha->format('Y-m-d')
		];
		$estado = model(EstadoVenta::class)->create($data)->save();
		return true;
	}
}
