<?php

namespace App\Http\Middleware;

use App\Models\Language;
use App\Services\Localization\LanguageService;
use Closure;
use Illuminate\Database\QueryException;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\App;
use Illuminate\Support\Facades\Schema;
use Illuminate\Support\Facades\View;
use Symfony\Component\HttpFoundation\Response;

class ResolveActiveLanguage
{
    public function handle(Request $request, Closure $next): Response
    {
        $language = $this->resolve($request);
        $direction = $language?->direction ?? 'ltr';

        App::setLocale($language?->code ?? 'en');
        View::share('currentLanguage', $language);
        View::share('layoutDirection', $direction);
        View::share('activeLanguages', $this->activeLanguagePayload());
        View::share('booklioTranslationPayload', $this->translationPayload($language));

        return $next($request);
    }

    private function resolve(Request $request): ?Language
    {
        try {
            if (! Schema::hasTable('languages')) {
                return null;
            }

            if (! Language::query()->exists()) {
                app(LanguageService::class)->ensureDefaults();
            }

            $code = $request->query('lang');

            if ($code) {
                $language = Language::query()->where('code', $code)->where('is_active', true)->first();

                if ($language) {
                    $request->session()->put('booklio_locale', $language->code);

                    return $language;
                }
            }

            $sessionCode = $request->session()->get('booklio_locale');

            if ($sessionCode) {
                $language = Language::query()->where('code', $sessionCode)->where('is_active', true)->first();

                if ($language) {
                    return $language;
                }
            }

            return app(LanguageService::class)->defaultLanguage();
        } catch (QueryException) {
            return null;
        }
    }

    private function activeLanguagePayload(): array
    {
        try {
            return app(LanguageService::class)->activeLanguages()->map(fn (Language $language) => [
                'code' => $language->code,
                'name' => $language->name,
                'native' => $this->nativeName($language),
                'direction' => $language->direction,
                'enabled' => $language->is_active,
                'default' => $language->is_default,
            ])->all();
        } catch (QueryException) {
            return [];
        }
    }

    private function translationPayload(?Language $language): array
    {
        try {
            if (! Schema::hasTable('languages')) {
                return [
                    'defaultLocale' => 'en',
                    'currentLocale' => 'en',
                    'direction' => 'ltr',
                    'languages' => [],
                ];
            }

            return app(LanguageService::class)->translationPayload($language);
        } catch (QueryException) {
            return [
                'defaultLocale' => 'en',
                'currentLocale' => 'en',
                'direction' => 'ltr',
                'languages' => [],
            ];
        }
    }

    private function nativeName(Language $language): string
    {
        if ($language->code === 'ar') {
            return json_decode('"\u0627\u0644\u0639\u0631\u0628\u064a\u0629"', false, 512, JSON_THROW_ON_ERROR);
        }

        if ($language->code === 'ur') {
            return json_decode('"\u0627\u0631\u062f\u0648"', false, 512, JSON_THROW_ON_ERROR);
        }

        return match ($language->code) {
            'ar' => 'العربية',
            'ur' => 'اردو',
            default => $language->native_name,
        };
    }
}
