<?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\Contact\StoreContactRequest;
use Maestro\Core\Modules\Customers\Http\Requests\Contact\UpdateContactRequest;
use Maestro\Core\Modules\Customers\Http\Resources\ContactResource;
use Maestro\Core\Modules\Customers\Models\Contact;
use Maestro\Core\Modules\Customers\Models\Customer;

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

        $contacts = $customer->contacts()->orderByDesc('is_primary')->orderBy('last_name')->get();

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

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

        $validated = $request->validated();

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

        /** @var Contact $contact */
        $contact = $customer->contacts()->create([
            ...$validated,
            'is_primary' => $isPrimary,
        ]);

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

    public function update(UpdateContactRequest $request, Customer $customer, Contact $contact): JsonResponse
    {
        $this->assertCustomerScope($request, $customer);
        $this->assertContactBelongs($customer, $contact);

        $validated = $request->validated();

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

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

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

    public function destroy(Request $request, Customer $customer, Contact $contact): JsonResponse
    {
        $this->assertCustomerScope($request, $customer);
        $this->assertContactBelongs($customer, $contact);
        $contact->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 assertContactBelongs(Customer $customer, Contact $contact): void
    {
        abort_if((int) $contact->customer_id !== (int) $customer->id, 404);
    }
}
