<?php

namespace App\Modules\Bookings\Targets;

use App\Modules\Bookings\Task;
use Illuminate\Support\Facades\DB;
use App\Models\User;

class RepairsTarget
{
	/**
	 * The user for which the stats are for.
	 *
	 * @var \User
	 */
    protected $user;

    /**
     * The start date.
     *
     * @var string
     */
    protected $start_date;

    /**
     * The end date.
     *
     * @var string
     */
    protected $end_date;

    /**
     * The total labour.
     *
     * @var float
     */
    protected $labour_total;

    /**
     * The total parts.
     *
     * @var float
     */
    protected $parts_total;

    /**
     * The total score for QAs
     *
     * @var float
     */
    protected $qa_total;

    /**
     * The total points received for contract (labour free) jobs.
     *
     * @var int
     */
    protected $contract_total;

    /**
     * Creates a new instance of the Repairs target.
     *
     * @param \User $user
     */
    public function __construct($user)
    {
        $this->user = $user;
    }

    /**
     * Creates a new instace for the given user.
     *
     * @param  \User   $user
     * @return static
     */
    public static function user(User $user)
    {
        return new static($user);
    }

    /**
     * Sets the start date.
     *
     * @param  mixed $date
     * @return self
     */
    public function startDate($date)
    {
        if (is_numeric($date)) {
            $date = date('Y-m-d H:i:s', $date);
        }

        $this->start_date = $date;
        return $this;
    }

    /**
     * Sets the end date.
     *
     * @param  mixed $date
     * @return self
     */
    public function endDate($date)
    {
        if (is_numeric($date)) {
            $date = date('Y-m-d H:i:s', $date);
        }

        $this->end_date = $date;
        return $this;
    }

    /**
     * Returns the target for the user.
     *
     * @return float
     */
    public function getTarget()
    {
        return $this->user->repair_target ? : -1;
    }

    /**
     * Checks if the user has a target.
     *
     * @return boolean
     */
    public function hasTarget()
    {
    	return $this->user->repair_target ? true : false;
    }

    /**
     * Returns the total labour.
     *
     * @return float
     */
    public function getLabourTotal()
    {
        if ($this->labour_total) {
            return $this->labour_total;
        }

        $this->labour_total = Task::where('type', 'repair')
			->where('assigned_to', $this->user->id)
			->where('completed_at', '>=', $this->start_date)
			->where('completed_at', '<=', $this->end_date)
			->sum('labour');

        return $this->labour_total;
    }

    /**
     * Returns the total amount of parts.
     *
     * @return float
     */
    public function getPartsTotal()
    {
        if ($this->parts_total) {
            return $this->parts_total;
        }

        $total = Task::select(DB::raw('SUM(parts.quantity * parts.price * (parts.vat / 100 + 1)) as total'))
			->join('parts', function ($q) {
				$q->on('parts.related_id', '=', 'tasks.id')->where('parts.related_type', '=', 'task');
			})
			->where('type', 'repair')
			->where('tasks.assigned_to', $this->user->id)
			->where('tasks.completed_at', '>=', $this->start_date)
			->where('tasks.completed_at', '<=', $this->end_date)
			->first();

        $this->parts_total = round($total->total * 10 / 100, 2); // get 10% of the parts
		return $this->parts_total;
    }

    /**
     * Returns the total score for QAs.
     *
     * @return float
     */
    public function getQATotal()
    {
        $this->qa_total = Task::where('tasks.type', 'qa')
            ->join('tasks as b', 'tasks.qa_id', '=', 'b.id')
            ->where('tasks.assigned_to', $this->user->id)
            ->where('tasks.completed_at', '>=', $this->start_date)
            ->where('tasks.completed_at', '<=', $this->end_date)
            ->where('b.type', 'repair')
            ->count() * 5; // £5 per QA

        return $this->qa_total;
    }

    /**
     * Returns the total amount of points to receive
     * for contract jobs, the ones with free labour.
     *
     * @return int
     */
    public function getContractTotal()
    {
        $tasks = Task::with('standard_price')
            ->where('type', 'repair')
            ->where('assigned_to', $this->user->id)
            ->where('labour', 0)
            ->where('completed_at', '>=', $this->start_date)
            ->where('completed_at', '<=', $this->end_date)
            ->get();

        $this->contract_total = $tasks->reduce(function ($points, $task) {
            return $points + $task->points;
        });

        return $this->contract_total;
    }

    /**
     * Returns the total income amount, by adding
     * up the labour and parts.
     *
     * @return float
     */
    public function getTotal()
    {
        return $this->getPartsTotal() + $this->getLabourTotal() + $this->getQATotal() + $this->getContractTotal();
    }

    /**
     * Returns the percentage to the target.
     *
     * @return float
     */
    public function getPercentage()
    {
        return 100 / $this->getTarget() * $this->getTotal();
    }

    /**
     * Exports all the values as an array.
     *
     * @return array | null
     */
    public function toArray()
    {
        if (! $this->hasTarget() ) {
            return;
        }

        return [
            'target'   => $this->getTarget(),
            'parts'    => $this->getPartsTotal(),
            'labour'   => $this->getLabourTotal(),
            'qa'       => $this->getQATotal(),
            'contract' => $this->getContractTotal(),
            'total'    => $this->getTotal(),
            'percent'  => $this->getPercentage(),
		];
    }
}
