<?php

namespace App\Modules\HR\Recruitment\Controllers;

use App\Http\Controllers\Controller;
use App\Modules\HR\Recruitment\DTOs\ApplicationWriteData;
use App\Modules\HR\Recruitment\Models\RecruitmentApplication;
use App\Modules\HR\Recruitment\Repositories\RecruitmentApplicationRepository;
use App\Modules\HR\Recruitment\Repositories\RecruitmentVacancyRepository;
use App\Modules\HR\Recruitment\Requests\StoreApplicationRequest;
use App\Modules\HR\Recruitment\Requests\UpdateApplicationRequest;
use App\Modules\HR\Recruitment\Requests\UpdateApplicationStatusRequest;
use App\Modules\HR\Recruitment\Services\RecruitmentApplicationService;
use App\Modules\HR\Recruitment\Support\ApplicationStatus;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\View\View;

class ApplicationsPageController extends Controller
{
    public function __construct(
        private readonly RecruitmentApplicationService $service,
        private readonly RecruitmentApplicationRepository $repository,
        private readonly RecruitmentVacancyRepository $vacancies,
    ) {}

    public function index(Request $request): View
    {
        $this->authorize('viewAny', RecruitmentApplication::class);
        $tenantId = $this->tenantId();

        return view('pages.hr.recruitment.applications.index', [
            'applications' => $this->repository->paginateForTenant($tenantId, [
                'q' => $request->string('q')->toString() ?: null,
                'status' => $request->string('status')->toString() ?: null,
                'vacancy_id' => $request->integer('vacancy_id') ?: null,
            ]),
            'statusOptions' => $this->statusOptions(),
            'vacancyOptions' => collect($this->vacancies->searchForLookup($tenantId, '', 50))
                ->mapWithKeys(fn ($o) => [$o['value'] => $o['label']])
                ->all(),
        ]);
    }

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

        return view('pages.hr.recruitment.applications.create', [
            'statusOptions' => $this->statusOptions(false),
        ]);
    }

    public function store(StoreApplicationRequest $request): RedirectResponse
    {
        $this->service->store(
            ApplicationWriteData::fromValidated($request->validated()),
            (int) $request->user()->id,
        );

        return redirect()
            ->route('hr.recruitment.applications.index')
            ->with('status', __('recruitment.applications.flash.created'));
    }

    public function edit(RecruitmentApplication $application): View
    {
        $this->authorize('update', $application);

        return view('pages.hr.recruitment.applications.edit', [
            'application' => $application->load(['candidate', 'vacancy', 'candidateCv']),
            'statusOptions' => $this->statusOptions(false),
        ]);
    }

    public function update(UpdateApplicationRequest $request, RecruitmentApplication $application): RedirectResponse
    {
        $this->service->update($application, ApplicationWriteData::fromValidated($request->validated()));

        return redirect()
            ->route('hr.recruitment.applications.index')
            ->with('status', __('recruitment.applications.flash.updated'));
    }

    public function updateStatus(UpdateApplicationStatusRequest $request, RecruitmentApplication $application): RedirectResponse
    {
        $this->service->updateStatus($application, (string) $request->validated('status'));

        return back()->with('status', __('recruitment.applications.flash.status_updated'));
    }

    public function destroy(RecruitmentApplication $application): RedirectResponse
    {
        $this->authorize('delete', $application);
        $this->service->destroy($application);

        return redirect()
            ->route('hr.recruitment.applications.index')
            ->with('status', __('recruitment.applications.flash.deleted'));
    }

    /** @return array<string, string> */
    private function statusOptions(bool $withAll = true): array
    {
        $opts = $withAll ? ['' => __('recruitment.filters.all')] : [];
        foreach (ApplicationStatus::all() as $s) {
            $opts[$s] = __('recruitment.applications.status.'.$s);
        }

        return $opts;
    }

    private function tenantId(): int
    {
        $id = auth()->user()?->tenant_id;
        abort_if($id === null, 403);

        return (int) $id;
    }
}
