<?php

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

use App\Domain\Agents\Enums\AgentStatus;
use App\Domain\Agents\Models\Agent;
use App\Domain\Agents\Services\AgentService;
use App\Domain\Identity\Services\ScopeGuard;
use App\Http\Controllers\Controller;
use App\Http\Requests\Agents\StoreAgentRequest;
use App\Http\Requests\Agents\UpdateAgentRequest;
use App\Http\Resources\AgentResource;
use App\Support\ApiResponse;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;

class AgentController extends Controller
{
    public function __construct(
        private readonly AgentService $agents,
        private readonly ScopeGuard $scopes,
    ) {}

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

        $query = Agent::query()->with(['branch:id,uuid,name', 'supervisor:id,uuid,name']);
        $this->scopes->apply($query, $request->user(), 'agent.view');

        $agents = $query
            ->when($request->filled('search'), function ($builder) use ($request) {
                $search = '%'.$request->string('search').'%';
                $builder->where(fn ($q) => $q
                    ->where('name', 'like', $search)
                    ->orWhere('agent_code', 'like', $search)
                    ->orWhere('phone', 'like', $search)
                    ->orWhere('territory', 'like', $search));
            })
            ->when($request->filled('status'), fn ($b) => $b->where('status', $request->string('status')))
            ->when($request->boolean('operational_only'), fn ($b) => $b->operational())
            ->orderBy('name')
            ->paginate($request->integer('per_page', 25));

        return ApiResponse::success(
            AgentResource::collection($agents),
            meta: ['statuses' => $this->statusOptions()],
        );
    }

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

        $agent->load([
            'branch:id,uuid,name',
            'supervisor:id,uuid,name',
            'user:id,uuid,email',
            'statusHistories.changedBy:id,name',
        ]);

        return ApiResponse::success(new AgentResource($agent));
    }

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

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

        $agent = $this->agents->create($attributes, $request->user());

        return ApiResponse::success(
            new AgentResource($agent->load('branch:id,uuid,name')),
            'Agent registered and awaiting approval.',
            status: 201,
        );
    }

    public function update(UpdateAgentRequest $request, Agent $agent): JsonResponse
    {
        $this->authorize('update', $agent);

        $agent = $this->agents->update($agent, $request->modelAttributes(), $request->user());

        return ApiResponse::success(
            new AgentResource($agent->load('branch:id,uuid,name')),
            'Agent updated successfully.',
        );
    }

    /** @return array<int, array{value: string, label: string}> */
    private function statusOptions(): array
    {
        return array_map(
            fn (AgentStatus $status) => ['value' => $status->value, 'label' => $status->label()],
            AgentStatus::cases(),
        );
    }
}
