<?php

namespace App\Http\Controllers\Api\V1\PublicSite;

use App\Domain\Documents\Models\DocumentRequirement;
use App\Domain\Recruitment\Models\JobDemand;
use App\Domain\Website\Models\DestinationCountry;
use App\Domain\Website\Models\JobCategory;
use App\Http\Controllers\Controller;
use App\Http\Resources\Public\PublicJobDetailResource;
use App\Http\Resources\Public\PublicJobResource;
use App\Support\ApiResponse;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;

/** The public jobs portal (§162). */
class PublicJobController extends Controller
{
    public function index(Request $request): JsonResponse
    {
        $jobs = JobDemand::publiclyVisible()
            ->with(['employer:id,company_name', 'jobCategory:id,slug,name'])
            ->when($request->filled('search'), function ($query) use ($request) {
                $search = '%'.$request->string('search').'%';
                $query->where(fn ($q) => $q
                    ->where('job_title', 'like', $search)
                    ->orWhere('occupation', 'like', $search)
                    ->orWhere('public_summary', 'like', $search));
            })
            ->when($request->filled('country'), fn ($q) => $q->where('country', strtoupper($request->string('country')->toString())))
            ->when($request->filled('category'), fn ($q) => $q->whereHas(
                'jobCategory', fn ($c) => $c->where('slug', $request->string('category'))
            ))
            ->when($request->filled('min_salary'), fn ($q) => $q->where('salary_amount', '>=', $request->integer('min_salary')))
            ->when($request->filled('max_experience'), fn ($q) => $q->where(
                fn ($e) => $e->whereNull('required_experience_years')
                    ->orWhere('required_experience_years', '<=', $request->integer('max_experience'))
            ))
            ->when($request->boolean('featured'), fn ($q) => $q->where('is_featured', true))
            ->when($request->boolean('urgent'), fn ($q) => $q->where('is_urgent', true))
            ->orderByDesc('is_urgent')
            ->orderByDesc('is_featured')
            ->latest('publish_at')
            ->paginate(min($request->integer('per_page', 12), 48));

        return ApiResponse::success(
            PublicJobResource::collection($jobs),
            meta: [
                'filters' => [
                    'countries' => DestinationCountry::published()
                        ->orderBy('sort_order')
                        ->get(['code', 'name', 'slug'])
                        ->map(fn ($country) => [
                            'code' => $country->code,
                            'name' => $country->name,
                            'count' => JobDemand::publiclyVisible()->where('country', $country->code)->count(),
                        ])
                        ->filter(fn (array $country) => $country['count'] > 0)
                        ->values(),
                    'categories' => JobCategory::published()
                        ->orderBy('sort_order')
                        ->get(['id', 'slug', 'name'])
                        ->map(fn ($category) => [
                            'slug' => $category->slug,
                            'name' => $category->name,
                            'count' => JobDemand::publiclyVisible()->where('job_category_id', $category->id)->count(),
                        ])
                        ->filter(fn (array $category) => $category['count'] > 0)
                        ->values(),
                ],
            ],
        );
    }

    public function show(string $slug): JsonResponse
    {
        $job = JobDemand::publiclyVisible()
            ->with(['employer:id,company_name', 'jobCategory:id,slug,name'])
            ->where('public_slug', $slug)
            ->first();

        // A withdrawn or unpublished job is simply not there, with no hint that
        // it ever was.
        if ($job === null) {
            return ApiResponse::error('This job is no longer available.', [], 404);
        }

        // Documents a candidate will be asked for, resolved from the configured
        // requirements for this demand and destination (§17A).
        $job->publicRequiredDocuments = DocumentRequirement::query()
            ->where('company_id', $job->company_id)
            ->where('is_active', true)
            ->where('is_mandatory', true)
            ->where(fn ($q) => $q->whereNull('destination_country')->orWhere('destination_country', $job->country))
            ->where(fn ($q) => $q->whereNull('job_demand_id')->orWhere('job_demand_id', $job->id))
            ->with('documentType:id,name,category,is_active')
            ->get()
            ->filter(fn (DocumentRequirement $requirement) => $requirement->documentType?->is_active)
            ->map(fn (DocumentRequirement $requirement) => $requirement->documentType->name)
            ->unique()
            ->values()
            ->all();

        return ApiResponse::success(new PublicJobDetailResource($job));
    }
}
