<?php
namespace Incoviba\old\Venta;

use Carbon\Carbon;
use Incoviba\Common\Factory\Model as Factory;
use Incoviba\Common\Alias\OldModel as Model;
use Incoviba\old\Proyecto\Proyecto;

/**
 * @property int $id
 * @property Proyecto $proyecto
 * @property float $precio
 * @property \DateTime $fecha
 * @property int $relacionado
 * @property Propietario $propietario
 */
class Cierre extends Model
{
  const VIGENTES = 1;
  const NO_VIGENTES = -1;
  public static function find(Proyecto $proyecto, Unidad $unidad, float $precio)
  {
    return model(Cierre::class)
      ->select('cierre.*')
      ->join('unidad_cierre', ['unidad_cierre.cierre', '=', 'cierre.id'])
      ->where('cierre.proyecto', $proyecto->id)
      ->where('unidad_cierre.unidad', $unidad->id)
      ->where('cierre.precio', $precio);
  }
  public static function vigentes()
  {
    return model(Cierre::class)
      ->select('cierre.*')
      ->join('estado_cierre', ['estado_cierre.cierre', '=', 'cierre.id'])
      ->join('tipo_estado_cierre', ['tipo_estado_cierre.id', '=', 'estado_cierre.tipo'])
      ->join('proyecto', ['proyecto.id', '=', 'cierre.proyecto'])
      ->where('tipo_estado_cierre.vigente', 1)
      ->orderByAsc('proyecto.descripcion')
      ->orderByAsc('cierre.fecha')
      ->groupBy('cierre.id')
      ->findMany();
  }
  public static function proyectos()
  {
    return model(Proyecto::class)
      ->select('proyecto.*')
      ->join('cierre', ['proyecto.id', '=', 'cierre.proyecto'])
      ->join('estado_cierre', ['estado_cierre.cierre', '=', 'cierre.id'])
      ->join('tipo_estado_cierre', ['tipo_estado_cierre.id', '=', 'estado_cierre.tipo'])
      ->where('tipo_estado_cierre.vigente', 1)
      ->orderByAsc('proyecto.descripcion')
      ->orderByAsc('cierre.fecha')
      ->groupBy('proyecto.id')
      ->findMany();
  }

  public function proyecto()
  {
    return $this->belongsTo(Proyecto::class, 'proyecto')->findOne();
  }
  public function unidades()
  {
    return $this->hasMany(UnidadCierre::class, 'cierre')->where('principal', 0)->findMany();
  }
  public function unidadPrincipal()
  {
    return $this->hasMany(UnidadCierre::class, 'cierre')->where('principal', 1)->findOne();
  }
  public function fecha(\DateTime $fecha = null)
  {
    if ($fecha == null) {
      return Carbon::parse($this->fecha, config('app.timezone'));
    }
    $this->fecha = $fecha->format('Y-m-d');
  }
  public function propietario()
  {
    $propietario = $this->belongsTo(Propietario::class, 'propietario');
    if ($propietario) {
      return $propietario->findOne();
    }
    return false;
  }
  public function uf_m2()
  {
    return $this->neto() / $this->unidadPrincipal()->unidad()->m2();
  }
  public function neto()
  {
    $valor = $this->precio;
    foreach ($this->unidades() as $unidad) {
      $valor -= $unidad->unidad()->precio($this->fecha())->valor;
    }
    foreach ($this->valores() as $v) {
      if ($v->tipo()->descripcion == 'pie') {
        continue;
      }
      $valor -= $v->valor;
    }
    return $valor;
  }
  public function valores()
  {
    return $this->hasMany(ValorCierre::class, 'cierre')->findMany();
  }
  public function valor($tipo = 'pie')
  {
    return $this->hasMany(ValorCierre::class, 'cierre')
      ->select('valor_cierre.*')
      ->join('tipo_valor_cierre', ['tipo_valor_cierre.id', '=', 'valor_cierre.tipo'])
      ->where('tipo_valor_cierre.descripcion', $tipo)
      ->findOne();
  }
  public function estados()
  {
    return $this->hasMany(EstadoCierre::class, 'cierre')->findMany();
  }
  public function estado(\DateTime $fecha = null)
  {
    if ($fecha == null) {
      $estado = $this->hasMany(EstadoCierre::class, 'cierre')->orderByDesc('id')->findOne();
      if ($estado->tipo()->vigente == 1 and $this->oldest()) {
        if ($this->promesa() and $estado->tipo()->descripcion != 'promesado') {
          $tipo = model(TipoEstadoCierre::class)->where('descripcion', 'promesado')->findOne();
          $data = [
            'cierre' => $this->id,
            'tipo' => $tipo->id,
            'fecha' => $this->promesa()->fecha
          ];
          $estado = model(EstadoCierre::class)->create($data);
          $estado->save();
        }
      }
    } else {
      $estado = $this->hasMany(EstadoCierre::class, 'cierre')->whereLte('fecha', $fecha->format('Y-m-d'))->orderByDesc('id')->findOne();
    }
    return $estado;
  }
  public function isVigente(): bool {
    if ($this->estado()->tipo()->vigente == 1) {
      return true;
    }
    return false;
  }
  public function new(\DateTime $fecha)
  {
    $this->save();
    $tipo = model(TipoEstadoCierre::class)->where('descripcion', 'revisado')->findOne();
    $data = [
      'cierre' => $this->id,
      'tipo' => $tipo->id,
      'fecha' => $fecha->format('Y-m-d')
    ];
    $estado = model(EstadoCierre::class)->create($data);
    $estado->save();

    if ($this->other()) {
      $this->replace($fecha);
    }
  }
  protected function cierresUnidad() {
    $up = $this->unidadPrincipal();
    if (!$up) {
      return false;
    }
    $up = $up->id;
    $cierres = model(Cierre::class)
      ->select('cierre.*')
      ->join('unidad_cierre', ['unidad_cierre.cierre', '=', 'cierre.id'])
      ->where('unidad_cierre.unidad', $up)
      ->findMany();
    $id = $this->id;
    $cierres = array_filter($cierres, function($item) use ($id) {
      return ($id != $item->id);
    });
    return $cierres;
  }
  protected function other(): bool {
    $cierres = $this->cierresUnidad();
    if ($cierres and count($cierres) > 0) {
      return true;
    }
    return false;
  }
  protected function oldest(): bool {
    if ($this->other()) {
      $last = $this->cierresUnidad()[count($this->cierresUnidad()) - 1];
      if ($last->fecha < $this->fecha) {
        return true;
      }
      return false;
    }
    return true;
  }
  protected function replace(\DateTime $fecha) {
    $cierres = $this->cierresUnidad();
    $tipo = model(TipoEstadoCierre::class)->where('descripcion', 'abandonado')->findOne();
    array_walk($cierres, function($item) use ($tipo, $fecha) {
      $data = [
        'cierre' => $item->id,
        'tipo' => $tipo->id,
        'fecha' => $fecha->format('Y-m-d')
      ];
      $estado = model(EstadoCierre::class)->create($data);
      $estado->save();
    });
  }
  public function addUnidad(array $data)
  {
    $data['cierre'] = $this->id;
    $unidad = model(UnidadCierre::class)->create($data);
    $unidad->save();
  }
  public function addValor(array $data)
  {
    $data['cierre'] = $this->id;
    $tipo = model(TipoValorCierre::class)->where('descripcion', $data['tipo'])->findOne();
    $data['tipo'] = $tipo->id;
    $valor = model(ValorCierre::class)->create($data);
    $valor->save();
  }
  public static function evaluar($precio_neto, $unidad, $fecha, $relacionado = false)
  {
    $precio_oferta = round($precio_neto, 2);
    $precio_lista = round($unidad->precio($fecha)->valor * (($relacionado) ? (1 - 0.06) : 1), 2);
    if ($precio_oferta >= $precio_lista) {
      return true;
    }
    return false;
  }
  public function guardar(object $input)
  {
    $this->proyecto = $input->proyecto->id;
    $this->precio = $input->precio;
    $this->fecha = $input->fecha->format('Y-m-d');
    $this->relacionado = 0;
    if (isset($input->relacionado) and $input->relacionado) {
      $this->relacionado = 1;
    }
    if (isset($input->subrelacionado) and $input->subrelacionado) {
      $this->relacionado = 2;
    }
    $fecha = Carbon::today(config('app.timezone'));
    $this->new($fecha);

    $data = [
      'unidad' => $input->departamento->id,
      'principal' => 1
    ];
    $this->addUnidad($data);

    foreach ($input->unidades as $unidad) {
      $data = ['unidad' => $unidad->id];
      $this->addUnidad($data);
    }

    if (isset($input->pie)) {
      $data = [
        'tipo' => 'pie',
        'valor' => $input->pie
      ];
      $this->addValor($data);
    }
    if (isset($input->bono)) {
      $data = [
        'tipo' => 'bono pie',
        'valor' => $input->bono
      ];
      $this->addValor($data);
    }
    if (isset($input->promocion)) {
      $data = [
        'tipo' => 'premio',
        'valor' => $input->promocion
      ];
      $this->addValor($data);
    }
    if (isset($input->operador)) {
      $data = [
        'tipo' => 'operador',
        'valor' => $input->operador * $this->precio / 100
      ];
      $this->addValor($data);
    }
  }
  public function aprobar(\DateTime $fecha)
  {
    $tipo = model(TipoEstadoCierre::class)->where('descripcion', 'aprobado')->findOne();
    $data = [
      'cierre' => $this->id,
      'tipo' => $tipo->id
    ];
    $estado = (new Factory(EstadoCierre::class))->where($data)->find();
    if (!$estado) {
      $data['fecha'] = $fecha->format('Y-m-d');
      $estado = model(EstadoCierre::class)->create($data);
      $estado->save();
    }
  }
  public function rechazar(\DateTime $fecha)
  {
    $tipo = model(TipoEstadoCierre::class)->where('descripcion', 'rechazado')->findOne();
    $data = [
      'cierre' => $this->id,
      'tipo' => $tipo->id
    ];
    $estado = (new Factory(EstadoCierre::class))->where($data)->find();
    if (!$estado) {
      $data['fecha'] = $fecha->format('Y-m-d');
      $estado = model(EstadoCierre::class)->create($data);
      $estado->save();
    }
  }
  protected $promesa;
  public function promesa()
  {
    if ($this->promesa == null) {
      $propiedad = model(Propiedad::class)->where('unidad_principal', $this->unidadPrincipal()->unidad)->findOne();
      if (!$propiedad) {
        return false;
      }
      $this->promesa = model(Venta::class)->where('propiedad', $propiedad->id)->where('estado', 1)->findOne();
      if ($this->promesa != null and $this->propietario == 0) {
        $this->propietario = $this->promesa->propietario;
        $this->save();
      }
    }
    return $this->promesa;
  }
  public function isRelacionado() {
    return ($this->relacionado == 1) ? true : false;
  }
  public function isSubrelacionado() {
    return ($this->relacionado == 2) ? true : false;
  }
  public function periodo() {
    $today = Carbon::today(config('app.timezone'));
    $dif = $today->diffInDays($this->fecha());
    return $dif;
  }
}
