<?php

namespace Modules\SystemCore\App\Http\Controllers;

use App\Http\Controllers\Controller;
use Illuminate\Http\JsonResponse;
use Modules\SystemCore\App\Http\Requests\StoreContactRequest;
use Modules\SystemCore\App\Http\Requests\UpdateContactRequest;
use Modules\SystemCore\App\Models\CoreContact;
use Modules\SystemCore\App\Models\CoreCustomer;
use Modules\SystemCore\App\Models\CoreSupplier;

class EntityContactController extends Controller
{
    /**
     * Map of entity types to their model classes
     *
     * @var array<string, class-string>
     */
    protected array $entityTypeMap = [
        'customer' => CoreCustomer::class,
        'supplier' => CoreSupplier::class,
    ];

    /**
     * Store a newly created contact.
     */
    public function store(StoreContactRequest $request): JsonResponse
    {
        $validated = $request->validated();

        // Verify the entity exists
        $entityModel = $this->entityTypeMap[$validated['entity_type']] ?? null;
        if (! $entityModel) {
            return response()->json([
                'success' => false,
                'message' => __('Invalid entity type.'),
            ], 422);
        }

        $entity = $entityModel::find($validated['entity_id']);
        if (! $entity) {
            return response()->json([
                'success' => false,
                'message' => __('Entity not found.'),
            ], 404);
        }

        // If this is set as primary, unset other primary contacts for this entity
        if (! empty($validated['is_primary'])) {
            CoreContact::where('entity_type', $validated['entity_type'])
                ->where('entity_id', $validated['entity_id'])
                ->where('is_primary', true)
                ->update(['is_primary' => false]);
        }

        $contact = CoreContact::create($validated);

        return response()->json([
            'success' => true,
            'message' => __('Contact created successfully.'),
            'data' => $contact,
        ], 201);
    }

    /**
     * Display the specified contact.
     */
    public function show(string $entityType, int $entityId, int $contact): JsonResponse
    {
        $contactModel = CoreContact::where('id', $contact)
            ->where('entity_type', $entityType)
            ->where('entity_id', $entityId)
            ->first();

        if (! $contactModel) {
            return response()->json([
                'success' => false,
                'message' => __('Contact not found.'),
            ], 404);
        }

        return response()->json([
            'success' => true,
            'message' => __('Contact retrieved successfully.'),
            'data' => $contactModel,
        ]);
    }

    /**
     * Update the specified contact.
     */
    public function update(UpdateContactRequest $request, string $entityType, int $entityId, int $contact): JsonResponse
    {
        $contactModel = CoreContact::where('id', $contact)
            ->where('entity_type', $entityType)
            ->where('entity_id', $entityId)
            ->first();

        if (! $contactModel) {
            return response()->json([
                'success' => false,
                'message' => __('Contact not found.'),
            ], 404);
        }

        $validated = $request->validated();

        // If this is set as primary, unset other primary contacts for this entity
        if (! empty($validated['is_primary']) && ! $contactModel->is_primary) {
            CoreContact::where('entity_type', $contactModel->entity_type)
                ->where('entity_id', $contactModel->entity_id)
                ->where('id', '!=', $contactModel->id)
                ->where('is_primary', true)
                ->update(['is_primary' => false]);
        }

        $contactModel->update($validated);

        return response()->json([
            'success' => true,
            'message' => __('Contact updated successfully.'),
            'data' => $contactModel->fresh(),
        ]);
    }

    /**
     * Remove the specified contact.
     */
    public function destroy(string $entityType, int $entityId, int $contact): JsonResponse
    {
        $contactModel = CoreContact::where('id', $contact)
            ->where('entity_type', $entityType)
            ->where('entity_id', $entityId)
            ->first();

        if (! $contactModel) {
            return response()->json([
                'success' => false,
                'message' => __('Contact not found.'),
            ], 404);
        }

        $wasPrimary = $contactModel->is_primary;

        $contactModel->delete();

        // If the deleted contact was primary, set the first remaining contact as primary
        if ($wasPrimary) {
            $nextContact = CoreContact::where('entity_type', $entityType)
                ->where('entity_id', $entityId)
                ->first();

            if ($nextContact) {
                $nextContact->update(['is_primary' => true]);
            }
        }

        return response()->json([
            'success' => true,
            'message' => __('Contact deleted successfully.'),
        ]);
    }

    /**
     * Set a contact as primary.
     */
    public function setPrimary(string $entityType, int $entityId, int $contact): JsonResponse
    {
        $contactModel = CoreContact::where('id', $contact)
            ->where('entity_type', $entityType)
            ->where('entity_id', $entityId)
            ->first();

        if (! $contactModel) {
            return response()->json([
                'success' => false,
                'message' => __('Contact not found.'),
            ], 404);
        }

        // Unset other primary contacts for this entity
        CoreContact::where('entity_type', $contactModel->entity_type)
            ->where('entity_id', $contactModel->entity_id)
            ->where('id', '!=', $contactModel->id)
            ->where('is_primary', true)
            ->update(['is_primary' => false]);

        // Set this contact as primary
        $contactModel->update(['is_primary' => true]);

        return response()->json([
            'success' => true,
            'message' => __('Contact set as primary successfully.'),
            'data' => $contactModel->fresh(),
        ]);
    }
}
