<?php

namespace Modules\Target\Controllers\Employee;

/** Ajax Request */

use App\Services\Response\ResponseService;
use Exception;
use Illuminate\Support\Facades\Auth;
use Illuminate\View\View;
use Illuminate\Http\Request;
use Illuminate\Http\JsonResponse;
use App\Http\Controllers\Controller;
use Maatwebsite\Excel\Facades\Excel;
use Modules\Target\Exports\ChartTargetExport;
use Modules\Target\Requests\Employee\TargetRequest;
use Modules\Target\Services\TargetService;
use Modules\MainService\Enums\ViewEnum;
use Modules\Product\Services\ProductService;
use Modules\Target\Enums\TargetLengthEnum;
use Modules\Target\Exports\TargetExport;
use Modules\Target\Requests\Employee\CreateTargetRequest;
use Modules\Target\Requests\Employee\EditTargetRequest;
use Modules\Target\Requests\Employee\FetchTargetRequest;
use Modules\User\Enums\UserRoleEnum;
use Modules\User\Services\UserService;

class TargetController extends Controller
{

    /** Redirect to this path after each operation success*/
    private $redirectSuccessPath= '/employee/targets';
    /** View folder */
    private $actionDirectory = 'employee.targets.';
    private $viewDirectory = 'employee.targets.';
    private $viewDirectoryTarget = 'employee.targets.target.';
    private $viewDirectoryTargetShow = 'employee.targets.targetShow.';
    //

    public function __construct(
        private TargetService $targetService,
        private UserService $userService,
        private ProductService $productService
    ){}

    /**
     * Display a listing of the targets.
     *
     * @param Request $request
     * @return View
     */
    public function index(Request $request) :View
    {
        $data =
        [
            'head'=>__('targets.head'),
            'view' => ViewEnum::INDEX->value,
            'route'=>$this->viewDirectory,
            'users' => $this->userService->get([
                'roles'=>UserRoleEnum::employees()
            ]),
            'request'=>$request,
            'times'=>TargetLengthEnum::values(),
        ];
        return $this->targetService->render($data);
    }

    /**
     * return data of the targets.
     *
     * @param Request $request
     * @return View
     */
    public function grid(Request $request)
    {

        if(isset($request->orderBy))
        {
            $orderBy = json_decode($request->orderBy, true);
            $request->merge(['orderBy'=>['key'=>$orderBy['key'], 'value'=>$orderBy['value']]]);
        }
        if($request->export)
        {
            $requestContent = array_merge($request->all(), [
                'employee_id' => auth()->user()->id,
            ]);
            $targets = $this->targetService->get($requestContent);
            return Excel::download(new TargetExport($targets,Auth::user()), 'targets.xlsx');
        }
        if($request->chart_export)
        {
            $employees = $this->userService->get([
                'name'=>$request['employee'] ?? null,
                'employeeFilter' => auth()->user(),
                'roles'=>UserRoleEnum::employees()
            ]);
            $products = $this->productService->get();
            $year = date('Y');
            $months = [
                0 => 1,
                1 => 2,
                2 => 3,
                3 => "Q1",
                4 => 4,
                5 => 5,
                6 => 6,
                7 => "Q2",
                8 => "S1",
                9 => 7,
                10 => 8,
                11 => 9,
                12 => "Q3",
                13 => "YTD",
                14 => 10,
                15 => 11,
                16 => 12,
                17 => "Q4",
                18 => "S2",
                19 => "FY",
            ];
            return Excel::download(new ChartTargetExport($employees,$products,$year,$months), 'targets.xlsx');
        }
        $request->merge([
            'paginate' => true,
            'route' => $this->viewDirectory,
            'view' => ViewEnum::LIST->value,
            'groupBy'=>'default',
            'request'=>$request,
            'users' => $this->userService->get([
                'roles'=>UserRoleEnum::employees()
            ]),
            'lengthes'=>TargetLengthEnum::values(),
            'employeeFilter' => auth()->user(),
        ]);

        return $this->targetService->renderView($request->all());
    }

    public function fetchTarget(FetchTargetRequest $request)
    {
        $products = $this->targetService->getTarget($request->all());

        $request->merge([
            'route' => $this->viewDirectoryTarget,
            'view' => ViewEnum::INDEX->value,
            'request'=>$request,
            'products' => $products
        ]);
        return $this->targetService->renderView($request->all());
    }

    public function fetchTargetShow(FetchTargetRequest $request)
    {
        $products = $this->targetService->getTarget($request->all());

        $request->merge([
            'route' => $this->viewDirectoryTargetShow,
            'view' => ViewEnum::INDEX->value,
            'request'=>$request,
            'products' => $products
        ]);
        return $this->targetService->renderView($request->all());
    }
    /**
     * Show the form for creating a new target.
     *
     * @return View
     */
    public function create() :View
    {
        $data =
        [
            'head'=>__('targets.new'),
            'action' => route($this->actionDirectory.'store'),
            'view' => ViewEnum::CREATE->value,
            'route'=> $this->viewDirectory,
            'users' => $this->userService->get([
                'roles'=>UserRoleEnum::employees()
            ]),
            'lengthes'=>TargetLengthEnum::values(),
            'products'=>$this->productService->get(),
            'times'=>TargetLengthEnum::values(),
        ];
        return $this->targetService->render($data);
    }

    /**
     * Store a newly created target in storage.
     * @param CreateTargetRequest $request
     * @return JsonResponse
     */
    public function store(CreateTargetRequest $request) :JsonResponse
    {
        $this->targetService->create($request->validated());

        session()->flash('message', __('dashboard.saveDone'));
        $response = [
            'status'=>200,
            'message'=>__('web.success'),
            'data'=> route($this->actionDirectory.'index'),
        ];
        return ResponseService::response($response);
    }

    /**
     * Show the form for editing the specified target.
     *
     * @param  int $id
     * @return View
     */
    public function edit(int $id) :View
    {
        $target = $this->targetService->getItem($id);
        if (!$target)
        {
            abort(404);
        }
        $data =
        [
            'head'=>__('targets.edit'),
            'action' => route($this->actionDirectory.'update',$target->id),
            'view' => ViewEnum::EDIT->value,
            'route'=> $this->viewDirectory,
            'target'=>$target
        ];
        return $this->targetService->render($data);
    }

    public function show(Request $request) :View
    {
        $months = $this->targetService->getMonths([
            'employee_id'=>$request->employee_id,
            'product_id'=>$request->product_id,
            'year'=>$request->year
        ]);

        $quarters = array_map(fn($month) => ceil($month / 3), $months);


        $months = array_values(array_unique($quarters));

        $data =
            [
                'head'=>__('targets.new'),
                'action' => route('targets.store'),
                'view' => ViewEnum::SHOW->value,
                'route'=> $this->viewDirectory,
                'users' => $this->userService->get([
                    'roles'=>UserRoleEnum::employees()
                ]),
                'request'=>$request,
                'months'=>$months,
                'employee'=>$this->userService->getItem($request->employee_id),
                'lengthes'=>TargetLengthEnum::values(),
                'products'=>$this->productService->get(),
                'times'=>TargetLengthEnum::values(),
            ];
        return $this->targetService->render($data);
    }

    public function editTarget (Request $request)
    {
        $months = $this->targetService->getMonths([
            'employee_id'=>$request->employee_id,
            'product_id'=>$request->product_id,
            'year'=>$request->year
        ]);

        $quarters = array_map(fn($month) => ceil($month / 3), $months);


        $months = array_values(array_unique($quarters));

        $data =
            [
                'head'=>__('targets.new'),
                'action' => route('targets.store'),
                'view' => ViewEnum::CREATE->value,
                'route'=> $this->viewDirectory,
                'users' => $this->userService->get([
                    'roles'=>UserRoleEnum::employees()
                ]),
                'request'=>$request,
                'months'=>$months,
                'lengthes'=>TargetLengthEnum::values(),
                'products'=>$this->productService->get(),
                'times'=>TargetLengthEnum::values(),
            ];
        return $this->targetService->render($data);
    }

    /**
     * Update the specified target in storage.
     * @param EditTargetRequest $request
     * @param int $id
     * @return JsonResponse
     */
    public function update(EditTargetRequest $request, int $id) :JsonResponse
    {
        $target = $this->targetService->checkItem($id);
        if (!$target)
        {
            abort(404);
        }
        $this->targetService->update($request->validated(), $id);
        session()->flash('message', __('dashboard.saveDone'));
        $response = [
            'status'=>200,
            'message'=>__('web.success'),
            'data'=> route($this->actionDirectory.'index'),
        ];
        return ResponseService::response($response);
    }

    /**
     * Remove the specified target from storage.
     * @param int $id
     * @return JsonResponse
     * @throws Exception
     */
    public function destroy(int $id) :JsonResponse
    {
        $this->targetService->destroy($id);
        session()->flash('message', __('dashboard.saveDone'));
        $response = [
            'status'=>200,
            'message'=>__('web.success'),
            'data'=> route($this->actionDirectory.'index'),
        ];
        return ResponseService::response($response);
    }

    /**
     * Remove several targets by IDs.
     *
     * @param Request $request
     * @return JsonResponse
     */
    public function destroyAll(Request $request) :JsonResponse
    {
        $this->targetService->destroyAll([
            'ids' => $request->ids,
            'status' => 1
        ]);
        $response = [
            'status'=>200,
            'message'=>__('web.success'),
            'data'=> route($this->actionDirectory.'index'),
        ];
        return ResponseService::response($response);
    }

    /**
     * Restore the specified target from storage.
     *
     * @param int $id
     * @return JsonResponse
     */
    public function restore(int $id) :JsonResponse
    {
        $this->targetService->destroy($id);
        $response = [
            'status'=>200,
            'message'=>__('web.success'),
            'data'=> route($this->actionDirectory.'index'),
        ];
        return ResponseService::response($response);
    }

    /**
     * Restore several targets by IDs.
     *
     * @param Request $request
     * @return JsonResponse
     */
    public function restoreAll(Request $request) :JsonResponse
    {
        $this->targetService->destroyAll([
            'ids' => $request->ids,
            'status' => 0
        ]);
        $response = [
            'status'=>200,
            'message'=>__('web.success'),
            'data'=> route($this->actionDirectory.'index'),
        ];
        return ResponseService::response($response);
    }
}
