<?php

namespace App\Modules\HR\Loans\Controllers;

use App\Http\Controllers\Controller;
use App\Modules\HR\Employees\Repositories\EmployeeRepository;
use App\Modules\HR\Loans\DTOs\LoanData;
use App\Modules\HR\Loans\Models\Loan;
use App\Modules\HR\Loans\Repositories\LoanRepository;
use App\Modules\HR\Loans\Requests\LoanRequest;
use App\Modules\HR\Loans\Services\LoanService;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\View\View;

class LoanController extends Controller
{
    public function __construct(
        private readonly LoanRepository $repository,
        private readonly LoanService $service,
        private readonly EmployeeRepository $employees,
    ) {}

    public function index(Request $request): JsonResponse|View
    {
        $this->authorize('viewAny', Loan::class);

        $loans = $this->repository->paginateForIndex((int) auth()->user()->tenant_id, $request);

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

    public function create(): JsonResponse|View
    {
        $this->authorize('create', Loan::class);

        $types = ['loan', 'advance'];
        if (request()->expectsJson()) {
            return response()->json(compact('types'));
        }

        return view('pages.hr.loans.create', [
            'types' => $types,
            'employees' => $this->employees->listForSelect((int) auth()->user()->tenant_id),
        ]);
    }

    public function store(LoanRequest $request): JsonResponse|RedirectResponse
    {
        $loan = $this->service->create(LoanData::fromValidated($request->validated()), (int) $request->user()->tenant_id, (int) $request->user()->id);

        return $request->expectsJson()
            ? response()->json($loan, 201)
            : redirect()->route('hr.loans.show', $loan)->with('success', __('loans.flash.created'));
    }

    public function show(Loan $loan): JsonResponse|View
    {
        $this->authorize('view', $loan);

        $loan->load(['employee', 'installments']);

        return request()->expectsJson() ? response()->json($loan) : view('pages.hr.loans.show', compact('loan'));
    }

    public function edit(Loan $loan): JsonResponse|View
    {
        $this->authorize('update', $loan);

        $loan->load('installments');
        if (request()->expectsJson()) {
            return response()->json($loan);
        }

        return view('pages.hr.loans.create', [
            'loan' => $loan, 'types' => ['loan', 'advance'],
            'employees' => $this->employees->listForSelect((int) auth()->user()->tenant_id),
        ]);
    }

    public function update(LoanRequest $request, Loan $loan): JsonResponse|RedirectResponse
    {
        $this->authorize('update', $loan);
        abort_unless($loan->status === 'draft', 422);

        $loan = $this->repository->update($loan, $request->validated());

        return $request->expectsJson()
            ? response()->json($loan)
            : redirect()->route('hr.loans.show', $loan)->with('success', __('loans.flash.updated'));
    }

    public function action(Loan $loan, string $action): JsonResponse|RedirectResponse
    {
        $this->authorize(in_array($action, ['approve', 'reject'], true) ? 'approve' : 'manage', $loan);

        $loan = $this->service->transition($loan, $action, (int) auth()->id());

        return request()->expectsJson()
            ? response()->json($loan)
            : back()->with('success', __('loans.flash.action'));
    }

    public function destroy(Loan $loan): JsonResponse|RedirectResponse
    {
        $this->authorize('manage', $loan);
        abort_unless($loan->status === 'draft', 422);
        $loan->delete();

        return request()->expectsJson()
            ? response()->json([], 204)
            : redirect()->route('hr.loans.index')->with('success', __('loans.flash.deleted'));
    }
}
