<?php

namespace App\Modules\HR\Recruitment\Repositories;

use App\Modules\HR\Recruitment\Models\RecruitmentApplication;
use App\Modules\HR\Recruitment\Models\RecruitmentHiring;
use App\Modules\HR\Recruitment\Models\RecruitmentInterview;
use App\Modules\HR\Recruitment\Models\RecruitmentJobRequest;
use App\Modules\HR\Recruitment\Models\RecruitmentOfferLetter;
use App\Modules\HR\Recruitment\Models\RecruitmentOnboardingCase;
use App\Modules\HR\Recruitment\Models\RecruitmentVacancy;
use App\Modules\HR\Recruitment\Support\ApplicationStatus;
use App\Modules\HR\Recruitment\Support\InterviewStatus;
use App\Modules\HR\Recruitment\Support\JobRequestStatus;
use App\Modules\HR\Recruitment\Support\OfferLetterStatus;
use App\Modules\HR\Recruitment\Support\OnboardingCaseStatus;
use App\Modules\HR\Recruitment\Support\VacancyStatus;
use Illuminate\Support\Collection;

class RecruitmentDashboardRepository
{
    public function countVacancies(int $tenantId, ?string $status = null): int
    {
        $q = RecruitmentVacancy::query()->where('tenant_id', $tenantId);
        if ($status !== null) {
            $q->where('status', $status);
        }

        return $q->count();
    }

    public function countApplications(int $tenantId, ?array $exclude = null): int
    {
        $q = RecruitmentApplication::query()->where('tenant_id', $tenantId);
        if ($exclude !== null) {
            $q->whereNotIn('status', $exclude);
        }

        return $q->count();
    }

    public function countByStatus(string $model, int $tenantId, string $status): int
    {
        return $model::query()->where('tenant_id', $tenantId)->where('status', $status)->count();
    }

    public function countHiringsThisMonth(int $tenantId): int
    {
        return RecruitmentHiring::query()
            ->where('tenant_id', $tenantId)
            ->where('hired_at', '>=', now()->startOfMonth())
            ->count();
    }

    public function countOnboarding(int $tenantId, string $status): int
    {
        return RecruitmentOnboardingCase::query()
            ->where('tenant_id', $tenantId)
            ->where('status', $status)
            ->count();
    }

    /** @return Collection<int, RecruitmentInterview> */
    public function upcomingInterviews(int $tenantId, int $limit = 8): Collection
    {
        return RecruitmentInterview::query()
            ->where('tenant_id', $tenantId)
            ->where('status', InterviewStatus::SCHEDULED)
            ->where('scheduled_at', '>=', now()->subDay())
            ->with(['application.candidate', 'application.vacancy'])
            ->orderBy('scheduled_at')
            ->limit($limit)
            ->get();
    }

    /** @return Collection<int, RecruitmentApplication> */
    public function recentApplications(int $tenantId, int $limit = 8): Collection
    {
        return RecruitmentApplication::query()
            ->where('tenant_id', $tenantId)
            ->with(['candidate', 'vacancy'])
            ->orderByDesc('applied_at')
            ->orderByDesc('id')
            ->limit($limit)
            ->get();
    }

    /** @return Collection<int, RecruitmentOnboardingCase> */
    public function activeOnboarding(int $tenantId, int $limit = 6): Collection
    {
        return RecruitmentOnboardingCase::query()
            ->where('tenant_id', $tenantId)
            ->where('status', OnboardingCaseStatus::IN_PROGRESS)
            ->with('employee')
            ->orderByDesc('id')
            ->limit($limit)
            ->get();
    }

    /** @return array<string, int> */
    public function applicationPipeline(int $tenantId): array
    {
        $rows = RecruitmentApplication::query()
            ->where('tenant_id', $tenantId)
            ->selectRaw('status, COUNT(*) as total')
            ->groupBy('status')
            ->pluck('total', 'status');

        $out = [];
        foreach (ApplicationStatus::all() as $status) {
            $out[$status] = (int) ($rows[$status] ?? 0);
        }

        return $out;
    }

    public function pendingJobRequests(int $tenantId): int
    {
        return $this->countByStatus(RecruitmentJobRequest::class, $tenantId, JobRequestStatus::PENDING_APPROVAL);
    }

    public function pendingOffers(int $tenantId): int
    {
        return $this->countByStatus(RecruitmentOfferLetter::class, $tenantId, OfferLetterStatus::SENT);
    }

    public function openVacancies(int $tenantId): int
    {
        return $this->countVacancies($tenantId, VacancyStatus::OPEN);
    }

    public function scheduledInterviews(int $tenantId): int
    {
        return $this->countByStatus(RecruitmentInterview::class, $tenantId, InterviewStatus::SCHEDULED);
    }
}
