<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use DB;

class Oti extends Model
{
    use HasFactory;

    protected $appends = ['piece_name', 'operator_name', 'client_name'];
    protected $fillable = ['piece', 'production_id', 'quantity', 'status', 'client_id', 'product_id', 'sector_id', 'details', 'calidad_id', 'alto', 'ancho', 'espesor', 'plisas', 'priority'];

    protected static function boot()
    {
        parent::boot();
        static::updated(function ($item) {
            return (new Oti)->checkFlowStatus($item);            
        });
    }

    public function pieza() 
    {
        return $this->hasOne(Pieza::class, 'id', 'piece');
    }

    public function sector() 
    {
        return $this->belongsTo(Sector::class, 'sector_id');
    }

    public function operator() 
    {
        return $this->hasOne(User::class, 'id', 'current_operator');
    }

    public function materials() 
    {
        return $this->hasMany(Material::class, 'id', 'material');
    }

    public function plans() 
    {
        return $this->belongsToMany(Plano::class, 'otis_plans');
    }

    public function op()
    {
        return $this->hasOne(OP::class, 'id', 'production_id'); //->withTrashed();
    }

    public function incidencias()
    {
        return $this->hasMany(Incidencia::class, 'oti_id')->with('tipo');
    }

    public function incidencia_pendiente()
    {
        return $this->hasMany(Incidencia::class, 'oti_id')->with('tipo')->where('status', 'PENDIENTE')->orderBy('id', 'DESC');
    }

    public function logs()
    {
        return $this->hasMany(OtiLog::class, 'oti_id');
    }

    public function getPieceNameAttribute()
    {
        return $this->pieza->name ?? '';
    }

    public function getOperatorNameAttribute()
    {
        if($this->operator){
            return $this->operator->name;
        }else{
            return null;
        }
        
    }

    public function getClientNameAttribute()
    {
        if($this->op){
            return $this->op->client->name ?? '';
        }else{
            return null;
        }
        
    }

    private function checkFlowStatus($item)
    {
        $oti_flujo = (new OtiFlujo)->where('oti_id', $item->id)->first();
        if (! $oti_flujo) {
            return;
        }
        $oti_flujo->status = $item->status;
        $oti_flujo->save();

        if ($oti_flujo->status == 3 || trim($oti_flujo->status) == "3") {
            $this->verifyStages($item, $oti_flujo);
        }
    }

    private function verifyStages($item, $oti_flujo)
    {
        $oti = (new Oti)->with('plans')->find($item->id);
        $production_id = $oti->production_id;

        $flujos_pendientes = (new OtiFlujo)
            ->whereIn('oti_id', function($query) use ($production_id) {
                $query->select('id')
                ->from(with(new Oti)->getTable())
                ->where('production_id', $production_id);            
            })
            ->where('status', '<', 3)
            ->first();

        if (! $flujos_pendientes ) {
            $this->checkToNewOti($oti_flujo, $oti);
        }
    }

    private function checkToNewOti($oti_flujo, $oti)
    {
        $prod_sector = (new ProductoSector)->find($oti_flujo->producto_sector_id);
        if (! $prod_sector) {
            return;
        }        
        $stg = (new ProductoSector)->where('stage', '>', $prod_sector->stage)->where('product_id', $prod_sector->product_id)->orderBy('stage')->first();

        if (! $stg) {
            return;
        }
        
        $prod_sectores = (new ProductoSector)->where('product_id', $stg->product_id)->where('stage', $stg->stage)->get();
        if (! $prod_sectores) {
            return;
        }

        foreach ($prod_sectores as $sector) {
            $oti_new = Oti::create([
                'piece' => $oti->piece,
                'production_id' => $oti->production_id,
                'quantity' => $oti->quantity,
                'status' => 0,
                'client_id' => $oti->client_id,
                'sector_id' => $sector->sector_id,
                'product_id' => $oti->product_id,
                'details' => $oti->details,
                'alto' => $oti->alto,
                'ancho' => $oti->ancho,
                'espesor' => $oti->espesor,
                'plisas' => $oti->plisas,
                'calidad_id' => $oti->calidad_id
            ]);

            $oti_flujo = OtiFlujo::create([
                'status' => 0,
                'producto_sector_id' => $sector->id,
                'oti_id' => $oti_new->id                        
            ]);

            $oti_plans = (new OtiPlan)->where('oti_id', $oti->id)->get();
            foreach ($oti_plans as $plano) {
                $oti_plan = OtiPlan::create([
                    'oti_id' => $oti_new->id,
                    'plano_id' => $plano->plano_id,
                ]);
            }
        }
    }

    public function getOrderByOperators()
    {
        return $this
            ->with('operator')
            ->select(DB::raw('current_operator'), DB::raw('SUM(CASE WHEN status = 4 THEN 1 ELSE 0 END) AS finalizado'), DB::raw('SUM(CASE WHEN status = 1 THEN 1 ELSE 0 END) AS proceso'), DB::raw('SUM(CASE WHEN status = 2 THEN 1 ELSE 0 END) AS pausa'))
            ->where('current_operator', '!=', null)
            ->groupBy('current_operator')
            ->orderBy('current_operator')
            ->take(10)
            ->get();
    }

}
