<?php

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

use App\Domain\Identity\Services\ScopeGuard;
use App\Domain\Recruitment\Enums\ComplianceStatus;
use App\Domain\Recruitment\Enums\EmployerStatus;
use App\Domain\Recruitment\Models\Employer;
use App\Domain\Recruitment\Services\EmployerService;
use App\Http\Controllers\Controller;
use App\Http\Requests\Recruitment\StoreEmployerRequest;
use App\Http\Requests\Recruitment\UpdateEmployerRequest;
use App\Http\Resources\EmployerResource;
use App\Support\ApiResponse;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;

class EmployerController extends Controller
{
    public function __construct(
        private readonly EmployerService $employers,
        private readonly ScopeGuard $scopes,
    ) {}

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

        $query = Employer::query()->with(['branch:id,uuid,name', 'primaryContact']);
        $this->scopes->apply($query, $request->user(), 'employer.view', 'account_manager_id');

        $employers = $query
            ->when($request->filled('search'), function ($builder) use ($request) {
                $search = '%'.$request->string('search').'%';
                $builder->where(fn ($q) => $q
                    ->where('company_name', 'like', $search)
                    ->orWhere('employer_code', 'like', $search)
                    ->orWhere('city', 'like', $search)
                    ->orWhere('email', '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->boolean('accepting_demands'), fn ($b) => $b->acceptingDemands())
            ->orderBy('company_name')
            ->paginate($request->integer('per_page', 25));

        return ApiResponse::success(
            EmployerResource::collection($employers),
            meta: [
                'statuses' => $this->options(EmployerStatus::cases()),
                'compliance_statuses' => $this->options(ComplianceStatus::cases()),
            ],
        );
    }

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

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

        return ApiResponse::success(new EmployerResource($employer));
    }

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

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

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

        if ($contacts = $request->contacts()) {
            $this->employers->syncContacts($employer, $contacts);
        }

        return ApiResponse::success(
            new EmployerResource($employer->load(['branch:id,uuid,name', 'contacts'])),
            'Employer created as a prospect.',
            status: 201,
        );
    }

    public function update(UpdateEmployerRequest $request, Employer $employer): JsonResponse
    {
        $this->authorize('update', $employer);

        $employer = $this->employers->update($employer, $request->modelAttributes(), $request->user());

        if (($contacts = $request->contacts()) !== null) {
            $this->employers->syncContacts($employer, $contacts);
        }

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

    /** @param array<int, EmployerStatus|ComplianceStatus> $cases */
    private function options(array $cases): array
    {
        return array_map(fn ($case) => ['value' => $case->value, 'label' => $case->label()], $cases);
    }
}
