<?php

namespace App\Modules\HR\Recruitment\Controllers;

use App\Http\Controllers\Controller;
use App\Modules\HR\Recruitment\DTOs\InterviewWriteData;
use App\Modules\HR\Recruitment\Models\RecruitmentInterview;
use App\Modules\HR\Recruitment\Repositories\RecruitmentApplicationRepository;
use App\Modules\HR\Recruitment\Repositories\RecruitmentInterviewRepository;
use App\Modules\HR\Recruitment\Requests\BulkDestroyInterviewsRequest;
use App\Modules\HR\Recruitment\Requests\StoreInterviewRequest;
use App\Modules\HR\Recruitment\Requests\UpdateInterviewRequest;
use App\Modules\HR\Recruitment\Services\RecruitmentInterviewService;
use App\Modules\HR\Recruitment\Support\InterviewMode;
use App\Modules\HR\Recruitment\Support\InterviewStatus;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\View\View;

class InterviewsPageController extends Controller
{
    public function __construct(
        private readonly RecruitmentInterviewService $service,
        private readonly RecruitmentInterviewRepository $repository,
        private readonly RecruitmentApplicationRepository $applications,
    ) {}

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

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

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

        return view('pages.hr.recruitment.interviews.create', $this->formShared());
    }

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

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

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

        return view('pages.hr.recruitment.interviews.edit', array_merge($this->formShared(), [
            'interview' => $interview->load(['application.candidate', 'application.vacancy', 'interviewer']),
        ]));
    }

    public function update(UpdateInterviewRequest $request, RecruitmentInterview $interview): RedirectResponse
    {
        $this->service->update($interview, InterviewWriteData::fromValidated($request->validated()));

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

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

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

    public function complete(RecruitmentInterview $interview): RedirectResponse
    {
        $this->authorize('update', $interview);
        $this->service->complete($interview);

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

    public function cancel(RecruitmentInterview $interview): RedirectResponse
    {
        $this->authorize('update', $interview);
        $this->service->cancel($interview);

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

    public function noShow(RecruitmentInterview $interview): RedirectResponse
    {
        $this->authorize('update', $interview);
        $this->service->markNoShow($interview);

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

    public function bulkDestroy(BulkDestroyInterviewsRequest $request): RedirectResponse
    {
        $count = $this->service->destroyMany($request->validated('ids'));

        return back()->with('status', __('recruitment.interviews.flash.bulk_deleted', ['count' => $count]));
    }

    /** @return array<string, mixed> */
    private function formShared(): array
    {
        $tenantId = $this->tenantId();

        return [
            'modeOptions' => collect(InterviewMode::all())
                ->mapWithKeys(fn ($m) => [$m => __('recruitment.interviews.mode.'.$m)])->all(),
            'statusOptions' => $this->statusOptions(false),
        ];
    }

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

        return $opts;
    }

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

        return (int) $id;
    }
}
