<?php

namespace FacturaScripts\Plugins\Partes\Model;

use FacturaScripts\Core\Model\Base;
use FacturaScripts\Core\Base\DataBase\DataBaseWhere;
use FacturaScripts\Core\Tools;
use FacturaScripts\Dinamic\Model\EstadoProyecto;
use FacturaScripts\Dinamic\Model\FaseTarea;
use FacturaScripts\Dinamic\Model\Proyecto;


class OIPlantillaTarea extends Base\ModelOnChangeClass
{
    use Base\ModelTrait;

    const TYPE_COMPLETED = 0;
    const TYPE_PROCESSING = 2;
    const TYPE_CANCELED = 1;

    /** @var int */
    public $cantidad;

    /** @var string */
    public $descripcion;

    /** @var string */
    public $fecha;

    /** @var string */
    public $fechafin;

    /** @var string */
    public $fechainicio;

    /** @var int */
    public $idfase;

    /** @var int */
    public $idproyecto;

    /** @var int */
    public $idtarea;

    /** @var string */
    public $nombre;

    public function clear()
    {
        parent::clear();
        $this->fecha = Tools::date();

        // select default status
        foreach ($this->getAvailablePhases() as $status) {
            if ($status->predeterminado) {
                $this->idfase = $status->idfase;
                break;
            }
        }
    }


    /**
     * @return FaseTarea[]
     */
    public function getAvailablePhases(): array
    {
        $available = [];
        $statusModel = new FaseTarea();
        foreach ($statusModel->all([], [], 0, 0) as $status) {
            $available[] = $status;
        }

        return $available;
    }

    /**
     * @return FaseTarea
     */
    public function getPhase()
    {
        $phase = new FaseTarea();
        $phase->loadFromCode($this->idfase);
        return $phase;
    }


    /**
     * @return Proyecto
     */
    public function getProject(): Proyecto
    {
        $project = new Proyecto();
        $project->loadFromCode($this->idproyecto);
        return $project;
    }

    public function install(): string
    {
        // needed dependencies
        new Proyecto();
        new FaseTarea();

        return parent::install();
    }


    public static function primaryColumn(): string
    {
        return "idplantilla";
    }

    public function primaryDescriptionColumn(): string
    {
        return "nombre";
    }

    public static function tableName(): string
    {
        return "oi_plantilla_tarea";
    }

    public function save(): bool
    {
        if (false === parent::save()) {
            return false;
        }

        $phase = $this->getPhase();
        if ($phase->predeterminado) {
            $this->setDefaultProjectStatus();
            return true;
        }

        if (null === $phase->idestado) {
            return true;
        }

        if (null === $phase->tipo) {
            $project = $this->getProject();
            $project->idestado = $phase->idestado;
            $project->save();
            return true;
        }

        $this->checkOtherTasks($phase);
        return true;
    }

    /**
     * We ask if all tasks in a project are completed or canceled.
     * If correct, we mark the status of the project with the linked phase
     *
     * @param FaseTarea $phase
     */
    protected function checkOtherTasks(FaseTarea $phase): void
    {
        $project = $this->getProject();
        $tasks = $project->getTasks();
        foreach ($tasks as $task) {
            if ($task->idfase !== $phase->idfase) {
                $this->deepTaskCheck($project, $tasks);
                return;
            }
        }

        $project->idestado = $phase->idestado;
        $project->save();
    }

    /**
     * We ask if the sum of the completed and canceled tasks is
     * equal to the total project tasks to complete it.
     *
     * @param Proyecto $project
     * @param OIPlantillaTarea[] $tasksplantilla
     */
    protected function deepTaskCheck(Proyecto $project, array $tasksplantilla): void
    {
        $completed = 0;
        $canceled = 0;
        foreach ($tasksplantilla as $task) {
            $phase = $task->getPhase();
            if ($phase->tipo === self::TYPE_COMPLETED) {
                $completed++;
            } elseif ($phase->tipo === self::TYPE_CANCELED) {
                $canceled++;
            }
        }

        if ($completed + $canceled === count($tasksplantilla)) {
            $phase = new FaseTarea();
            $where = [new DataBaseWhere('tipo', self::TYPE_COMPLETED)];
            if ($phase->loadFromCode('', $where)) {
                $project->idestado = $phase->idestado;
                $project->save();
            }
        }
    }

    /**
     * If the project is completed or canceled and a new task is added,
     * then it sets the default project status.
     */
    protected function setDefaultProjectStatus(): void
    {
        $defaultStatus = new EstadoProyecto();
        $where = [new DataBaseWhere('predeterminado', true)];
        if ($defaultStatus->loadFromCode('', $where)) {
            $project = $this->getProject();
            $project->idestado = $defaultStatus->idestado;
            $project->save();
        }
    }

}
