<?php

namespace App\Http\Controllers\api\v1;

use App\Http\Controllers\BaseController;

use App\Models\User;
use App\Models\ProfilePhoto;
use App\Modules\Bookings\Task;
use App\Modules\Bookings\Repair;
use App\Modules\Bookings\Support;
use App\Modules\Bookings\Onsite;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Response;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\File;
use Illuminate\Support\Facades\Config;
use Intervention\Image\Facades\Image;

class UsersControllerRESTv1 extends BaseController
{
    /**
     * Display a listing of the resource.
     *
     * @return Response
     */
    public function index(Request $request)
    {
        $query = User::select('*');

        if ($request->get('parts', false) == 'true') {
            $query->with('parts');
        }

        if ($request->get('active') && $request->get('active') != 'false') {
            $query->where('active', 1);
        }

        if ($request->get('inactive') && $request->get('inactive') != 'false') {
            $query->where('active', 0);
        }

        if ($request->get('suspended') && $request->get('suspended') != 'false') {
            $query->where('suspended', 1);
        }
        if ($request->has('extension')) {
            $query->where('extension', $request->get('extension'));
        }
        if ($request->has('direct_dial')) {
            $query->where('direct_dial', $request->get('direct_dial'));
        }

        if ($request->get('q')) {
            $query->where(DB::raw("CONCAT_WS(' ', first_name, last_name)"), 'like', '%' . $request->get('q') . '%');
        }

        $query->orderBy('first_name');

        $query = $query->paginate($request->get('limit', 20));

        $response = [
            'success'      => true,
            'data'         => $query->getCollection()->toArray(),
            'total'        => $query->total(),
            'current_page' => $query->currentPage(),
            'last_page'    => $query->lastPage(),
            'from'         => $query->firstItem(),
            'to'           => $query->lastItem(),
        ];

        return Response::json($response);
    }

    /**
     * Store a newly created resource in storage.
     *
     * @return Response
     */
    public function store(Request $request)
    {
        $user = User::create($request->all());

        if (!$user->id) {
            return Response::json(['errors' => $user->errors->all()], 400);
        }

        if ($user->account_type == 'oauth') {
            $user->load('oauth');
        }

        return $user;
    }

    /**
     * Display the specified resource.
     *
     * @param  int  $id
     *
     * @return Response
     */
    public function show($id)
    {
        $user = User::findOrFail($id);

        return Response::json($user->toArray());
    }

    /**
     * Update the specified resource in storage.
     *
     * @param  int  $id
     *
     * @return Response
     */
    public function update(Request $request, $id)
    {
        $user = User::findOrFail($id);
        $user->fill($request->all());

        if ($user->save()) {
            return Response::json($user->toArray());
        } else {
            return Response::json($user->errors->all(), 400);
        }
    }

    /**
     * Remove the specified resource from storage.
     *
     * @param  int  $id
     *
     * @return Response
     */
    public function destroy($id)
    { }

    public function profilePhoto(\App\Http\Requests\StoreUserRequest $request)
    {
        // Check to see if the profile photo exists
        $user = Auth::guest() ? User::findOrFail(getAuthUserId()) : Auth::user();
        $photo = $user->profile_photo()->first();
        if (!$photo) {
            $photo = new ProfilePhoto();
        } else {
            // Delete the previous photo
            File::delete(Config::get('files.photos_path') . '/' . $photo->filename);
        }

        $file = $request->file('files');

        // Generate a new filename
        $photo->fill([
            'name'     => $file->getClientOriginalName(),
            'size'     => $file->getSize(),
            'filename' => str_random(32) . '.' . $file->getClientOriginalExtension(),
            'user_id'  => $user->id,
        ]);

        $file = Image::make($request->file('files')->getRealPath());

        // Crop and resize
        $file->fit(200, 200);

        if ($file->save(Config::get('files.photos_path') . '/' . $photo->filename)) {
            if ($photo->save()) {
                return $photo;
            } else {
                // Delete the file
                File::delete(Config::get('files.photos_path') . '/' . $photo->filename);

                return Response::json(['errors' => $photo->errors->all()], 400);
            }
        } else {
            return Response::json(['error' => 'Unable to save file'], 400);
        }
    }

    public function getScores(Request $request)
    {
        // Retrieve all the techinicians
        // that have completed jobs this month
        switch ($request->get('task_type')) {
            case 'support':
                $list = Support::support()->select('assigned_to')->completed()->thisMonth($request->get('start_date'), $request->get('end_date'))->groupBy('assigned_to')->get()->toArray();
                break;

            case 'onsite':
                $list = Onsite::onsite()->select('assigned_to')->completed()->thisMonth($request->get('start_date'), $request->get('end_date'))->groupBy('assigned_to')->get()->toArray();
                break;

            default:
                $list = Repair::repairs()->select('assigned_to')->completed()->thisMonth($request->get('start_date'), $request->get('end_date'))->groupBy('assigned_to')->get()->toArray();
                break;
        }

        // We will flatten the list of users, to get just an array of their IDs
        $list = array_flatten($list);

        // If the array is empty, return here
        if (count($list) == 0) {
            return Response::json([]);
        }

        // Select only the users from the list above
        $users = User::whereIn('id', $list)->get();

        switch ($request->get('task_type')) {
            case 'support':
                return $this->getScoresSupport($users, $request);

            case 'onsite':
                return $this->getScoresOnsite($users, $request);

            default:
                return $this->getScoresRepairs($users, $request);
        }
    }

    protected function getScoresRepairs(&$users, Request $request)
    {
        foreach ($users as $user) {
            $query = Repair::select(DB::raw('COUNT(id) as cnt, SUM(labour) as labour'))->repairs()->where('assigned_to', $user->id)->completed()->thisMonth($request->get('start_date'), $request->get('end_date'))->first();
            $parts = Repair::leftJoin('parts', function ($join) {
                return $join->on('parts.related_id', '=', 'tasks.id')->where('parts.related_type', '=', 'task');
            })
                ->repairs()->where('completed', 1)->where('assigned_to', $user->id)->thisMonth($request->get('start_date'), $request->get('end_date'))
                ->select(DB::raw('SUM(parts.quantity * parts.price * (parts.vat / 100 + 1)) as total'))->first();

            $user->points_data = [
                'tasks'  => $query->cnt * 10,
                'labour' => round($query->labour * 20),
                'parts'  => round($parts->total),
            ];

            $user->points = array_sum($user->points_data);
        }

        return $users;
    }

    protected function getScoresSupport(&$users, Request $request)
    {
        foreach ($users as $user) {
            $query = Support::select(DB::raw('COUNT(id) as cnt, SUM(labour) as labour'))->support()->where('assigned_to', $user->id)->completed()->thisMonth($request->get('start_date'), $request->get('end_date'))->first();
            $parts = Support::leftJoin('parts', function ($join) {
                return $join->on('parts.related_id', '=', 'tasks.id')->where('parts.related_type', '=', 'task');
            })
                ->support()->where('completed', 1)->where('assigned_to', $user->id)->thisMonth($request->get('start_date'), $request->get('end_date'))
                ->select(DB::raw('SUM(parts.quantity * parts.price * (parts.vat / 100 + 1)) as total'))->first();

            $user->points_data = [
                'tasks'  => $query->cnt * 10,
                'labour' => round($query->labour * 20),
                'parts'  => round($parts->total),
            ];

            $user->points = array_sum($user->points_data);
        }

        return $users;
    }

    protected function getScoresOnsite(&$users, Request $request)
    {
        foreach ($users as $user) {
            $query = Onsite::select(DB::raw('COUNT(id) as cnt, SUM(labour) as labour'))->onsite()->where('assigned_to', $user->id)->completed()->thisMonth($request->get('start_date'), $request->get('end_date'))->first();
            $parts = Onsite::leftJoin('parts', function ($join) {
                return $join->on('parts.related_id', '=', 'tasks.id')->where('parts.related_type', '=', 'task');
            })
                ->onsite()->where('completed', 1)->where('assigned_to', $user->id)->thisMonth($request->get('start_date'), $request->get('end_date'))
                ->select(DB::raw('SUM(parts.quantity * parts.price * (parts.vat / 100 + 1)) as total'))->first();

            $user->points_data = [
                'tasks'  => $query->cnt * 10,
                'labour' => round($query->labour * 20),
                'parts'  => round($parts->total),
            ];

            $user->points = array_sum($user->points_data);
        }

        return $users;
    }
}
