<?php

namespace App\Modules\HR\Recruitment\Services;

use App\Modules\HR\Recruitment\DTOs\InterviewScorecardWriteData;
use App\Modules\HR\Recruitment\Events\RecruitmentInterviewScorecardCreated;
use App\Modules\HR\Recruitment\Events\RecruitmentInterviewScorecardDeleted;
use App\Modules\HR\Recruitment\Events\RecruitmentInterviewScorecardUpdated;
use App\Modules\HR\Recruitment\Models\RecruitmentInterviewScorecard;
use App\Modules\HR\Recruitment\Repositories\RecruitmentInterviewScorecardRepository;
use App\Support\SystemReferenceAssigner;
use App\Support\SystemReferenceGenerator;
use Illuminate\Contracts\Events\Dispatcher;
use Illuminate\Support\Facades\DB;

class RecruitmentInterviewScorecardService
{
    public function __construct(
        private readonly RecruitmentInterviewScorecardRepository $repository,
        private readonly SystemReferenceAssigner $references,
        private readonly Dispatcher $events,
    ) {}

    public function store(InterviewScorecardWriteData $data, int $userId): RecruitmentInterviewScorecard
    {
        $row = DB::transaction(function () use ($data, $userId) {
            $created = $this->repository->create(array_merge($data->toArray(), [
                'tenant_id' => $this->tenantId(),
                'reference_code' => $this->references->pendingPlaceholder(SystemReferenceGenerator::INTERVIEW_SCORECARD),
                'scored_by' => $userId,
                'scored_at' => now(),
            ]));

            return $this->references->assign(
                $created,
                SystemReferenceGenerator::INTERVIEW_SCORECARD,
                'reference_code'
            );
        });

        $this->events->dispatch(new RecruitmentInterviewScorecardCreated($row));

        return $row;
    }

    public function update(
        RecruitmentInterviewScorecard $row,
        InterviewScorecardWriteData $data,
    ): RecruitmentInterviewScorecard {
        $fresh = $this->repository->update($row, $data->toArray());
        $this->events->dispatch(new RecruitmentInterviewScorecardUpdated($fresh));

        return $fresh;
    }

    public function destroy(RecruitmentInterviewScorecard $row): void
    {
        $this->repository->softDelete($row);
        $this->events->dispatch(new RecruitmentInterviewScorecardDeleted($row));
    }

    /** @param  list<int>  $ids */
    public function destroyMany(array $ids): int
    {
        return $this->repository->softDeleteMany($this->tenantId(), $ids);
    }

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

        return (int) $id;
    }
}
