<?php

namespace Modules\SystemCore\App\Http\Controllers;

use App\Http\Controllers\Controller;
use Illuminate\Http\JsonResponse;
use Modules\SystemCore\App\Http\Requests\StoreAddressRequest;
use Modules\SystemCore\App\Http\Requests\UpdateAddressRequest;
use Modules\SystemCore\App\Models\CoreAddress;
use Modules\SystemCore\App\Models\CoreCustomer;
use Modules\SystemCore\App\Models\CoreSupplier;

class EntityAddressController 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 address.
     */
    public function store(StoreAddressRequest $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 addresses for this entity
        if (! empty($validated['is_primary'])) {
            CoreAddress::where('entity_type', $validated['entity_type'])
                ->where('entity_id', $validated['entity_id'])
                ->where('is_primary', true)
                ->update(['is_primary' => false]);
        }

        $address = CoreAddress::create($validated);

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

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

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

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

    /**
     * Update the specified address.
     */
    public function update(UpdateAddressRequest $request, string $entityType, int $entityId, int $address): JsonResponse
    {
        $addressModel = CoreAddress::where('id', $address)
            ->where('entity_type', $entityType)
            ->where('entity_id', $entityId)
            ->first();

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

        $validated = $request->validated();

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

        $addressModel->update($validated);

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

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

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

        $wasPrimary = $addressModel->is_primary;

        $addressModel->delete();

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

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

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

    /**
     * Set an address as primary.
     */
    public function setPrimary(string $entityType, int $entityId, int $address): JsonResponse
    {
        $addressModel = CoreAddress::where('id', $address)
            ->where('entity_type', $entityType)
            ->where('entity_id', $entityId)
            ->first();

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

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

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

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