<?php

declare(strict_types=1);

namespace Maestro\Core\Modules\Customers\Http\Controllers;

use Illuminate\Database\Eloquent\Builder;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Maestro\Core\Http\Controllers\Controller;
use Maestro\Core\Modules\Customers\Http\Requests\Customer\StoreCustomerRequest;
use Maestro\Core\Modules\Customers\Http\Requests\Customer\UpdateCustomerRequest;
use Maestro\Core\Modules\Customers\Http\Resources\CustomerResource;
use Maestro\Core\Modules\Customers\Models\Customer;

class CustomerController extends Controller
{
    /**
     * @return Builder<Customer>
     */
    private function baseQuery(Request $request): Builder
    {
        $organizationId = $request->user()?->organization_id;
        abort_if(! $organizationId, 403);

        return Customer::query()->where('organization_id', $organizationId);
    }

    public function index(Request $request): JsonResponse
    {
        $query = $this->baseQuery($request);

        $search = trim((string) $request->input('search', ''));
        if ($search !== '') {
            $query->where(function (Builder $q) use ($search) {
                $like = '%'.addcslashes($search, '%_\\').'%';
                $q->where('name', 'like', $like)
                    ->orWhere('email', 'like', $like)
                    ->orWhere('phone', 'like', $like);
            });
        }

        if ($request->has('filter_active')) {
            $query->where('is_active', $request->boolean('filter_active'));
        }

        $sortBy = $request->input('sort_by', 'name');
        $sortDir = strtolower((string) $request->input('sort_dir', 'asc')) === 'desc' ? 'desc' : 'asc';
        if (! in_array($sortBy, ['name', 'email', 'phone', 'is_active', 'created_at'], true)) {
            $sortBy = 'name';
        }
        $query->orderBy($sortBy, $sortDir);

        $perPage = min(max($request->integer('per_page', 15), 1), 100);

        return CustomerResource::collection($query->paginate($perPage))->response();
    }

    public function store(StoreCustomerRequest $request): JsonResponse
    {
        $organizationId = $request->user()?->organization_id;
        abort_if(! $organizationId, 403);

        $customer = Customer::create([
            ...$request->validated(),
            'organization_id' => $organizationId,
            'is_active' => $request->boolean('is_active', true),
        ]);

        return response()->json([
            'data' => new CustomerResource($customer->fresh()),
        ], 201);
    }

    public function show(Request $request, Customer $customer): JsonResponse
    {
        $this->assertSameOrganization($request, $customer);

        $customer->load(['contacts', 'addresses']);

        return response()->json([
            'data' => new CustomerResource($customer),
        ]);
    }

    public function update(UpdateCustomerRequest $request, Customer $customer): JsonResponse
    {
        $this->assertSameOrganization($request, $customer);

        $customer->fill($request->validated());
        $customer->save();

        return response()->json([
            'data' => new CustomerResource($customer->fresh()),
        ]);
    }

    public function destroy(Request $request, Customer $customer): JsonResponse
    {
        $this->assertSameOrganization($request, $customer);
        $customer->delete();

        return response()->json(['message' => 'Deleted.']);
    }

    private function assertSameOrganization(Request $request, Customer $customer): void
    {
        $organizationId = $request->user()?->organization_id;
        abort_if(! $organizationId, 403);
        abort_if((int) $customer->organization_id !== (int) $organizationId, 404);
    }
}
