<?php

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

use App\Domain\Identity\Services\ScopeGuard;
use App\Domain\Recruitment\Enums\JobDemandStatus;
use App\Domain\Recruitment\Models\Employer;
use App\Domain\Recruitment\Models\JobDemand;
use App\Domain\Recruitment\Services\JobDemandService;
use App\Http\Controllers\Controller;
use App\Http\Requests\Recruitment\StoreJobDemandRequest;
use App\Http\Requests\Recruitment\UpdateJobDemandRequest;
use App\Http\Resources\JobDemandResource;
use App\Support\ApiResponse;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;

class JobDemandController extends Controller
{
    public function __construct(
        private readonly JobDemandService $demands,
        private readonly ScopeGuard $scopes,
    ) {}

    public function index(Request $request): JsonResponse
    {
        $this->authorize('viewAny', JobDemand::class);

        $query = JobDemand::query()->with(['employer:id,uuid,company_name,country,status,compliance_status,agreement_expiry_date']);
        $this->scopes->apply($query, $request->user(), 'job_demand.view', 'owner_id');

        $demands = $query
            ->when($request->filled('search'), function ($builder) use ($request) {
                $search = '%'.$request->string('search').'%';
                $builder->where(fn ($q) => $q
                    ->where('job_title', 'like', $search)
                    ->orWhere('demand_code', 'like', $search)
                    ->orWhere('occupation', 'like', $search));
            })
            ->when($request->filled('status'), fn ($b) => $b->where('status', $request->string('status')))
            ->when($request->filled('country'), fn ($b) => $b->where('country', strtoupper($request->string('country')->toString())))
            ->when($request->filled('employer_id'), fn ($b) => $b->whereHas(
                'employer',
                fn ($q) => $q->where('uuid', $request->string('employer_id'))
            ))
            ->when($request->boolean('open_only'), fn ($b) => $b->open())
            ->latest('id')
            ->paginate($request->integer('per_page', 25));

        return ApiResponse::success(
            JobDemandResource::collection($demands),
            meta: [
                'statuses' => array_map(
                    fn (JobDemandStatus $status) => ['value' => $status->value, 'label' => $status->label()],
                    JobDemandStatus::cases(),
                ),
            ],
        );
    }

    public function show(JobDemand $jobDemand): JsonResponse
    {
        $this->authorize('view', $jobDemand);

        $jobDemand->load(['employer', 'branch:id,uuid,name', 'owner:id,uuid,name']);

        return ApiResponse::success(new JobDemandResource($jobDemand));
    }

    public function store(StoreJobDemandRequest $request): JsonResponse
    {
        $this->authorize('create', JobDemand::class);

        $employer = Employer::where('uuid', $request->string('employer_id'))->firstOrFail();

        // An employer outside the caller's scope must not be reachable by id.
        abort_unless($request->user()->can('view', $employer), 403);

        $attributes = $request->modelAttributes();
        $attributes['company_id'] = $request->user()->company_id;
        $attributes['branch_id'] ??= $request->user()->branch_id;
        $attributes['owner_id'] ??= $request->user()->getKey();

        $demand = $this->demands->create($attributes, $employer, $request->user());

        return ApiResponse::success(
            new JobDemandResource($demand->load(['employer', 'branch:id,uuid,name'])),
            'Job demand created as a draft.',
            status: 201,
        );
    }

    public function update(UpdateJobDemandRequest $request, JobDemand $jobDemand): JsonResponse
    {
        $this->authorize('update', $jobDemand);

        $demand = $this->demands->update($jobDemand, $request->modelAttributes(), $request->user());

        return ApiResponse::success(
            new JobDemandResource($demand->fresh()->load(['employer', 'branch:id,uuid,name'])),
            'Job demand updated successfully.',
        );
    }
}
