<?php

namespace App\Http\Controllers\Api\Tenant;

use App\Http\Controllers\Controller;
use App\Http\Requests\Tenant\EmotionStoreRequest;
use App\Http\Requests\Tenant\EmotionUpdateRequest;
use App\Http\Resources\Tenant\EmotionResource;
use App\Models\Emotion;
use App\Models\Tenant;
use App\Support\TenantRequestResolver;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Http\Resources\Json\AnonymousResourceCollection;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Schema;

class EmotionController extends Controller
{
    public function index(Request $request): AnonymousResourceCollection
    {
        $tenantId = $this->currentTenant($request)->id;

        $query = Emotion::query()
            ->when(true, function ($builder) use ($tenantId) {
                // Prefer tenant-specific and global emotions if the column exists
                if (Schema::hasColumn('emotions', 'tenant_id')) {
                    $builder->where(function ($inner) use ($tenantId) {
                        $inner->whereNull('tenant_id')
                            ->orWhere('tenant_id', $tenantId);
                    });
                }
            })
            ->with('eventTypes');

        if ($request->boolean('only_tenant')) {
            $query->where('tenant_id', $tenantId);
        }

        if ($request->boolean('only_global')) {
            $query->whereNull('tenant_id');
        }

        $query->orderByRaw('tenant_id is null desc')->orderBy('sort_order')->orderBy('id');

        $emotions = $query->paginate($request->integer('per_page', 50));

        if ($emotions->isEmpty() && ! $request->boolean('only_tenant')) {
            // Fallback: return any emotions regardless of tenant to avoid empty selectors
            $fallback = Emotion::query()
                ->with('eventTypes')
                ->orderBy('sort_order')
                ->orderBy('id')
                ->paginate($request->integer('per_page', 50));

            return EmotionResource::collection($fallback);
        }

        return EmotionResource::collection($emotions);
    }

    public function store(EmotionStoreRequest $request): JsonResponse
    {
        $data = $request->validated();
        $tenantId = $this->currentTenant($request)->id;

        $payload = [
            'tenant_id' => $tenantId,
            'name' => $this->localizeValue($data['name']),
            'description' => $this->localizeValue($data['description'] ?? null, allowNull: true),
            'icon' => $data['icon'] ?? 'lucide-smile',
            'color' => $this->normalizeColor($data['color'] ?? '#6366f1'),
            'sort_order' => $data['sort_order'] ?? 0,
            'is_active' => $data['is_active'] ?? true,
        ];

        $emotion = null;

        DB::transaction(function () use (&$emotion, $payload, $data) {
            $emotion = Emotion::create($payload);

            if (! empty($data['event_type_ids'])) {
                $emotion->eventTypes()->sync($data['event_type_ids']);
            }
        });

        return response()->json([
            'message' => __('Emotion erfolgreich erstellt.'),
            'data' => new EmotionResource($emotion->fresh('eventTypes')),
        ], 201);
    }

    public function update(EmotionUpdateRequest $request, Emotion $emotion): JsonResponse
    {
        $tenantId = $this->currentTenant($request)->id;

        if ($emotion->tenant_id && $emotion->tenant_id !== $tenantId) {
            abort(403, 'Emotion gehört nicht zu diesem Tenant.');
        }

        if (is_null($emotion->tenant_id) && $request->hasAny(['name', 'description', 'icon', 'color', 'sort_order'])) {
            abort(403, 'Globale Emotions können nicht bearbeitet werden.');
        }

        $data = $request->validated();

        DB::transaction(function () use ($emotion, $data) {
            $update = [];

            if (array_key_exists('name', $data)) {
                $update['name'] = $this->localizeValue($data['name'], allowNull: false, fallback: $emotion->name);
            }

            if (array_key_exists('description', $data)) {
                $update['description'] = $this->localizeValue($data['description'], allowNull: true, fallback: $emotion->description);
            }

            if (array_key_exists('icon', $data)) {
                $update['icon'] = $data['icon'] ?? $emotion->icon;
            }

            if (array_key_exists('color', $data)) {
                $update['color'] = $this->normalizeColor($data['color'] ?? $emotion->color);
            }

            if (array_key_exists('sort_order', $data)) {
                $update['sort_order'] = $data['sort_order'] ?? 0;
            }

            if (array_key_exists('is_active', $data)) {
                $update['is_active'] = $data['is_active'];
            }

            if (! empty($update)) {
                $emotion->update($update);
            }

            if (array_key_exists('event_type_ids', $data)) {
                $emotion->eventTypes()->sync($data['event_type_ids'] ?? []);
            }
        });

        return response()->json([
            'message' => __('Emotion aktualisiert.'),
            'data' => new EmotionResource($emotion->fresh('eventTypes')),
        ]);
    }

    protected function localizeValue(mixed $value, bool $allowNull = false, ?array $fallback = null): ?array
    {
        if ($allowNull && ($value === null || $value === '')) {
            return null;
        }

        if (is_array($value)) {
            $filtered = array_filter($value, static fn ($text) => is_string($text) && $text !== '');
            if (! empty($filtered)) {
                return $filtered;
            }

            return $allowNull ? null : ($fallback ?? []);
        }

        if (is_string($value) && $value !== '') {
            $locale = app()->getLocale() ?: 'de';

            return [$locale => $value];
        }

        return $allowNull ? null : $fallback;
    }

    protected function normalizeColor(string $color): string
    {
        $normalized = ltrim($color, '#');
        if (strlen($normalized) === 6) {
            return '#'.strtolower($normalized);
        }

        return '#6366f1';
    }

    protected function currentTenant(Request $request): Tenant
    {
        return TenantRequestResolver::resolve($request);
    }
}
