<?php

declare(strict_types=1);

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

use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Maestro\Core\Http\Controllers\Controller;
use Maestro\Core\Modules\Customers\Http\Requests\Address\StoreAddressRequest;
use Maestro\Core\Modules\Customers\Http\Requests\Address\UpdateAddressRequest;
use Maestro\Core\Modules\Customers\Http\Resources\AddressResource;
use Maestro\Core\Modules\Customers\Models\Address;
use Maestro\Core\Modules\Customers\Models\Customer;

class AddressController extends Controller
{
    public function index(Request $request, Customer $customer): JsonResponse
    {
        $this->assertCustomerScope($request, $customer);

        $addresses = $customer->addresses()->orderByDesc('is_primary')->orderBy('city')->get();

        return response()->json([
            'data' => AddressResource::collection($addresses),
        ]);
    }

    public function store(StoreAddressRequest $request, Customer $customer): JsonResponse
    {
        $this->assertCustomerScope($request, $customer);

        $validated = $request->validated();

        $isPrimary = (bool) ($validated['is_primary'] ?? false);
        if ($isPrimary) {
            $customer->addresses()->update(['is_primary' => false]);
        }

        /** @var Address $address */
        $address = $customer->addresses()->create([
            ...$validated,
            'is_primary' => $isPrimary,
        ]);

        return response()->json([
            'data' => new AddressResource($address),
        ], 201);
    }

    public function update(UpdateAddressRequest $request, Customer $customer, Address $address): JsonResponse
    {
        $this->assertCustomerScope($request, $customer);
        $this->assertAddressBelongs($customer, $address);

        $validated = $request->validated();

        if (array_key_exists('is_primary', $validated)) {
            if ($validated['is_primary']) {
                $customer->addresses()->where('id', '<>', $address->id)->update(['is_primary' => false]);
            }
        }

        $address->fill($validated);
        $address->save();

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

    public function destroy(Request $request, Customer $customer, Address $address): JsonResponse
    {
        $this->assertCustomerScope($request, $customer);
        $this->assertAddressBelongs($customer, $address);
        $address->delete();

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

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

    private function assertAddressBelongs(Customer $customer, Address $address): void
    {
        abort_if((int) $address->customer_id !== (int) $customer->id, 404);
    }
}
