<?php

namespace App\Modules\HR\Recruitment\Controllers;

use App\Http\Controllers\Controller;
use App\Modules\HR\Recruitment\DTOs\OfferLetterWriteData;
use App\Modules\HR\Recruitment\Models\RecruitmentOfferLetter;
use App\Modules\HR\Recruitment\Repositories\RecruitmentApplicationRepository;
use App\Modules\HR\Recruitment\Repositories\RecruitmentOfferLetterRepository;
use App\Modules\HR\Recruitment\Requests\BulkDestroyOfferLettersRequest;
use App\Modules\HR\Recruitment\Requests\StoreOfferLetterRequest;
use App\Modules\HR\Recruitment\Requests\UpdateOfferLetterRequest;
use App\Modules\HR\Recruitment\Services\RecruitmentOfferLetterAttachmentService;
use App\Modules\HR\Recruitment\Services\RecruitmentOfferLetterService;
use App\Modules\HR\Recruitment\Support\OfferLetterEmploymentType;
use App\Modules\HR\Recruitment\Support\OfferLetterStatus;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\View\View;

class OfferLettersPageController extends Controller
{
    public function __construct(
        private readonly RecruitmentOfferLetterService $service,
        private readonly RecruitmentOfferLetterRepository $repository,
        private readonly RecruitmentApplicationRepository $applications,
        private readonly RecruitmentOfferLetterAttachmentService $attachments,
    ) {}

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

        return view('pages.hr.recruitment.offer-letters.index', [
            'offers' => $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', RecruitmentOfferLetter::class);

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

    public function store(StoreOfferLetterRequest $request): RedirectResponse
    {
        $offer = $this->service->store(
            OfferLetterWriteData::fromValidated($request->validated()),
            (int) $request->user()->id,
        );
        foreach ($request->file('attachments', []) as $file) {
            $this->attachments->store($offer, $file, (int) $request->user()->id);
        }

        return redirect()
            ->route('hr.recruitment.offer-letters.show', $offer)
            ->with('status', __('recruitment.offer_letters.flash.created'));
    }

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

        return view('pages.hr.recruitment.offer-letters.edit', array_merge($this->formShared(), [
            'offer' => $offerLetter->load([
                'application', 'candidate', 'vacancy', 'department', 'position', 'employmentStatus',
            ]),
        ]));
    }

    public function update(UpdateOfferLetterRequest $request, RecruitmentOfferLetter $offerLetter): RedirectResponse
    {
        $this->service->update($offerLetter, OfferLetterWriteData::fromValidated($request->validated()));

        return redirect()
            ->route('hr.recruitment.offer-letters.show', $offerLetter)
            ->with('status', __('recruitment.offer_letters.flash.updated'));
    }

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

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

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

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

    public function duplicate(RecruitmentOfferLetter $offerLetter): RedirectResponse
    {
        $this->authorize('create', RecruitmentOfferLetter::class);
        $copy = $this->service->duplicate($offerLetter, (int) auth()->id());

        return redirect()
            ->route('hr.recruitment.offer-letters.edit', $copy)
            ->with('status', __('recruitment.offer_letters.flash.duplicated'));
    }

    /** @return array<string, mixed> */
    private function formShared(): array
    {
        return [
            'employmentTypeOptions' => collect(OfferLetterEmploymentType::all())
                ->mapWithKeys(fn ($t) => [$t => __('recruitment.offer_letters.employment_type.'.$t)])->all(),
        ];
    }

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

        return $opts;
    }

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

        return (int) $id;
    }
}
