<?php

namespace App\Modules\HR\Performance\Controllers;

use App\Http\Controllers\Controller;
use App\Modules\HR\Employees\Repositories\EmployeeRepository;
use App\Modules\HR\Performance\Models\PerformanceCycle;
use App\Modules\HR\Performance\Models\PerformanceReview;
use App\Modules\HR\Performance\Repositories\PerformanceRepository;
use App\Modules\HR\Performance\Requests\PerformanceRequest;
use App\Modules\HR\Performance\Services\PerformanceService;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\RedirectResponse;
use Illuminate\View\View;

class PerformanceController extends Controller
{
    public function __construct(
        private readonly PerformanceRepository $repository,
        private readonly PerformanceService $service,
        private readonly EmployeeRepository $employees,
    ) {}

    public function cycles(): JsonResponse|View
    {
        $cycles = $this->repository->cycles((int) auth()->user()->tenant_id);

        return request()->expectsJson() ? response()->json($cycles) : view('pages.hr.performance.cycles.index', compact('cycles'));
    }

    public function storeCycle(PerformanceRequest $r): JsonResponse|RedirectResponse
    {
        $cycle = $this->repository->saveCycle((int) $r->user()->tenant_id, $r->validated());

        return $r->expectsJson() ? response()->json($cycle, 201) : back()->with('success', __('performance.flash.created'));
    }

    public function updateCycle(PerformanceRequest $r, PerformanceCycle $cycle): JsonResponse|RedirectResponse
    {
        $cycle = $this->repository->saveCycle((int) $cycle->tenant_id, $r->validated(), $cycle);

        return $r->expectsJson() ? response()->json($cycle) : back()->with('success', __('performance.flash.updated'));
    }

    public function reviews(): JsonResponse|View
    {
        $employee = request()->routeIs('me.*') ? (int) auth()->user()->employee_id : null;

        $reviews = $this->repository->reviews((int) auth()->user()->tenant_id, $employee);
        if (request()->expectsJson()) {
            return response()->json($reviews);
        }
        if (request()->routeIs('me.*')) {
            return view('pages.me.performance.index', compact('reviews'));
        }

        return view('pages.hr.performance.reviews.index', [
            'reviews' => $reviews,
            'cycles' => $this->repository->cycleOptions((int) auth()->user()->tenant_id),
            'employees' => $this->employees->listForSelect((int) auth()->user()->tenant_id),
        ]);
    }

    public function storeReview(PerformanceRequest $r): JsonResponse|RedirectResponse
    {
        $review = $this->repository->saveReview((int) $r->user()->tenant_id, $r->validated());

        return $r->expectsJson() ? response()->json($review, 201) : back()->with('success', __('performance.flash.created'));
    }

    public function selfUpdate(PerformanceRequest $r, PerformanceReview $review): JsonResponse|RedirectResponse
    {
        abort_unless((int) $review->employee_id === (int) $r->user()->employee_id, 403);

        $review = $this->service->selfUpdate($review, $r->validated());

        return $r->expectsJson() ? response()->json($review) : back()->with('success', __('performance.flash.updated'));
    }

    public function managerUpdate(PerformanceRequest $r, PerformanceReview $review): JsonResponse|RedirectResponse
    {
        $review = $this->service->managerUpdate($review, $r->validated(), (int) $r->user()->id);

        return $r->expectsJson() ? response()->json($review) : back()->with('success', __('performance.flash.updated'));
    }

    public function destroyCycle(PerformanceCycle $cycle): JsonResponse|RedirectResponse
    {
        $this->repository->deleteCycle($cycle);

        return request()->expectsJson() ? response()->json([], 204) : back()->with('success', __('performance.flash.deleted'));
    }

    public function destroyReview(PerformanceReview $review): JsonResponse|RedirectResponse
    {
        $this->repository->deleteReview($review);

        return request()->expectsJson() ? response()->json([], 204) : back()->with('success', __('performance.flash.deleted'));
    }
}
