<?php

namespace App\Http\Livewire\Tags;

use App\Helpers\StringHelper;
use App\Http\Livewire\Traits\RequiresAdminAuthorization;
use App\Jobs\SendEmailNewTag;
use App\Models\Category;
use App\Models\Language;
use App\Models\Tag;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;
use Illuminate\Validation\Rule;
use Livewire\Component;
use WireUi\Traits\WireUiActions;

class Create extends Component
{
    use WireUiActions, RequiresAdminAuthorization;

    public bool $showCreateModal = false;
    public $createTag = [
        'name' => null,
        'language' => null,
        'category' => null,
        ];
    public $languages;
    public $localeOptions = [];
    public $categoryOptions = [];
    public $categorySelected = [
        'id' => null,
        'color' => 'gray',
        'path' => '',
    ];
    public $translationLanguages = [];
    public $selectTranslationLanguage;
    public $translationOptions = [];
    public $selectTagTranslation = null;
    public $inputTagTranslation = [];
    public bool $inputDisabled = true;
    public $translateRadioButton = null;


    public function mount()
    {
        // CRITICAL: Authorize admin access for tag creation component
        $this->authorizeAdminAccess();
    }

    protected function rules()
    {
        return [
            'createTag' => 'array',
            'createTag.name' => Rule::when(
                function ($input) {
                    // Check if createTag is not an empty array
                    return count($input['createTag']) > 0;
                },
                array_merge(
                    timebank_config('tags.name_rule'),
                    timebank_config('tags.exists_in_current_locale_rule'),
                    [
                        'sometimes',
                    ]
                ),
            ),
            'createTag.category' =>
                ['required', 'int'],
            'selectTagTranslation' => Rule::when(
                function ($input) {
                    // Check if existing tag translation is selected
                    return $this->translateRadioButton == 'select';
                },
                ['required', 'int'],
            ),
            'inputTagTranslation' => 'array',
            'inputTagTranslation.name' => Rule::when(
                fn ($input) => $this->translateRadioButton === 'input',
                array_merge(
                    timebank_config('tags.name_rule'),
                    timebank_config('tags.exists_in_current_locale_rule'),
                    [
                        'sometimes',
                        function ($attribute, $value, $fail) {
                            $existsInTransLationLanguage = DB::table('taggable_tags')
                                ->join('taggable_locales', 'taggable_tags.tag_id', '=', 'taggable_locales.taggable_tag_id')
                                ->where('taggable_locales.locale', $this->selectTranslationLanguage)
                                ->where(function ($query) use ($value) {
                                    $query->where('taggable_tags.name', $value)
                                        ->orWhere('taggable_tags.normalized', $value);
                                })
                                ->exists();

                            if ($existsInTransLationLanguage) {
                                $fail(__('This tag already exists.'));
                            }
                        },
                    ]
                ),
                []
            ),

        ];
    }


    public function openCreateModal()
    {
        $this->showCreateModal = true;

        $appLocale = app()->getLocale();

        $this->categoryOptions = Category::where('type', Tag::class)
            ->get()
            ->map(function ($category) {
                // Include all attributes, including appended ones
                return [
                    'category_id' => $category->id,
                    'name' => ucfirst($category->translation->name ?? ''), // Use the appended 'translation' attribute
                    'description' => $category->relatedPathExSelfTranslation ?? '', // Appended attribute
                    'color' => $category->relatedColor ?? 'gray',
                ];
            })
            ->sortBy('name')
            ->values();


        $this->languages = Language::all();
        $this->createTag['language'] = $appLocale;
        $this->localeOptions = $this->languages->filter(function ($lang) {
            return ($lang->lang_code);
        })->map(function ($lang) {
            return [
                'lang_code' => $lang->lang_code,
                'label'     => $lang->flag . ' ' . trans('messages.' . $lang->name),
            ];
        })->toArray();

        $this->updatedCreateTagLanguage();
    }


    public function updatedCreateTagCategory()
    {
        $this->categorySelected['color'] = Category::find($this->createTag['category'])->relatedColor ?? 'gray';

    }

    public function updatedCreateTagLanguage()
    {

        // Get languages to select translation language from: exclude the language already selected for the untranslated new tag.
        $optionLocales = array_diff($this->languages->pluck('lang_code')->toArray(), [$this->createTag['language']]);
        $this->translationLanguages = $this->languages->filter(function ($lang) use ($optionLocales) {
            return in_array($lang->lang_code, $optionLocales);
        })->map(function ($lang) {
            return [
                'lang_code' => $lang->lang_code,
                'name'     => $lang->flag . ' ' . trans('messages.' . $lang->name),
            ];
        })->toArray();
    }


    public function updatedSelectTranslationLanguage()
    {
        $this->selectTagTranslation = [];
        // Suggest related tags in the selected translation language
        $this->translationOptions = $this->getTranslationOptions($this->selectTranslationLanguage);

    }


    public function getTranslationOptions($locale)
    {
        $appLocale = $this->createTag['language'];

        // 1) Get all context_ids used by tags that match app()->getLocale()
        $contextIdsInAppLocale = DB::table('taggable_locale_context')
            ->whereIn('tag_id', function ($query) use ($appLocale) {
                $query->select('taggable_tag_id')
                    ->from('taggable_locales')
                    ->where('locale', $appLocale);
            })
            ->pluck('context_id');

        // 2) Exclude tags that share these context_ids
        $tags = Tag::with(['locale', 'contexts.category'])
            ->whereHas('locale', function ($query) use ($locale) {
                $query->where('locale', $locale);
            })
            ->whereNotIn('tag_id', function ($subquery) use ($contextIdsInAppLocale) {
                $subquery->select('tag_id')
                    ->from('taggable_locale_context')
                    ->whereIn('context_id', $contextIdsInAppLocale);
            })
            ->get();

        // 3) Build the options array. Adjust the name logic to your preference.
        $options = $tags->map(function ($tag) use ($locale) {
            $category = optional($tag->contexts->first())->category;
            $description = optional(optional($category)->translation)->name ?? '';

            return [
                'tag_id'      => $tag->tag_id,
                'name'        => $locale == 'de' ? $tag->name : StringHelper::DutchTitleCase($tag->normalized),
                'description' => $description,
            ];
        })->sortBy('name')->values();

        return $options;
    }


    public function updatedCreateTagName()
    {
        //Capitalize first letter of the strings, make sure that for German accents remain, using the mb_strupper function
        $this->createTag['name'] = app()->getLocale() == 'de' ? mb_strtoupper(mb_substr($this->createTag['name'], 0, 1)) : ucfirst($this->createTag['name']);
        $this->validateOnly('createTag.name');
    }


    public function updatedInputTagTranslationName()
    {
        //Capitalize first letter of the strings, make sure that for German accents remain, using the mb_strupper function
        $this->inputTagTranslation['name'] = app()->getLocale() == 'de' ? mb_strtoupper(mb_substr($this->createTag['name'], 0, 1)) : ucfirst($this->inputTagTranslation['name']);
        $this->validateOnly('inputTagTranslation.name');
    }





    public function updatedTranslateRadioButton()
    {
        if ($this->translateRadioButton === 'select') {
            $this->inputDisabled = true;
            $this->dispatch('disableInput');
        } elseif ($this->translateRadioButton === 'input') {
            $this->inputDisabled = false;
            // $this->dispatch('disableSelect'); // Script inside view skills-form.blade.php
        }
        $this->resetErrorBag('selectTagTranslation');
        $this->resetErrorBag('inputTagTranslation.name');
    }


    public function updatedSelectTagTranslation()
    {
        if ($this->selectTagTranslation) {
            $this->categorySelected['color'] = Tag::find($this->selectTagTranslation)->categories->first()->relatedColor ?? 'gray';
            $this->translateRadioButton = 'select';
            $this->dispatch('disableInput');
        } else {
            $this->selectTagTranslation = null;
        }
    }


    public function updatedInputTagTranslation()
    {
        $this->translateRadioButton = 'input';
        $this->inputDisabled = false;
        // $this->dispatch('disableSelect'); // Script inside view skills-form.blade.php
    }


    /**
     * Handles the save button of the create tag modal.
     *
     * Creates a new tag for the currently active profile and optionally
     * associates it with a category or base-language translation.
     *
     * @return void
     */
    public function create()
    {
        // CRITICAL: Authorize admin access for creating tag
        $this->authorizeAdminAccess();

        $this->validate();
        $this->resetErrorBag();

        // Format strings to correct case
        $this->createTag['name'] = app()->getLocale() == 'de' ? $this->createTag['name'] : StringHelper::DutchTitleCase($this->createTag['name']);

        $name = $this->createTag['name'];
        $normalized = call_user_func(config('taggable.normalizer'), $name);
        $updatedByUser = Auth::guard('web')->user()->id;    // use the logged user, not the active profile

        // Create the tag and context
        $tag = Tag::create([
            'name' => $name,
            'normalized' => $normalized,
            ]);

        $locale = [
            'locale' => $this->createTag['language'],
            'updated_by_user' => $updatedByUser,
        ];

        $context = [
            'category_id' => $this->createTag['category'],
            'updated_by_user' => $updatedByUser,
        ];

        if ($this->translateRadioButton === 'select') {
            // Attach an existing context in the base language to the new tag. See timebank_config('base_language')
            // Note that the category_id and updated_by_user is not updated when selecting an existing context
            $tagContext = Tag::find($this->selectTagTranslation)
                ->contexts()
                ->first();
            $tag->contexts()->attach($tagContext->id);

        } elseif ($this->translateRadioButton === 'input') {
            // Create a new context and locale for the new tag
            $tagContext = $tag->contexts()->create($context);

            // Create a new translation of the tag
            $this->inputTagTranslation['name'] = $this->selectTranslationLanguage == 'de' ? $this->inputTagTranslation['name'] : StringHelper::DutchTitleCase($this->inputTagTranslation['name']);
            // $owner->tag($this->inputTagTranslation['name']);
            $nameTranslation = $this->inputTagTranslation['name'];
            $normalizedTranslation = call_user_func(config('taggable.normalizer'), $nameTranslation);
            $locale = ['locale' => $this->selectTranslationLanguage ];

            // Create the translation tag with the locale and attach the context
            $tagTranslation = Tag::create([
                        'name' => $nameTranslation,
                        'normalized' => $normalizedTranslation,
                        ]);
            $tagTranslation->locale()->create($locale);
            $tagTranslation->contexts()->attach($tagContext->id);

        } else {
            // Create a new context for the new tag without translation
            $tagContext = $tag->contexts()->create($context);
        }

        // Create a new locale for the new tag
        $tagLocale = $tag->locale()->create($locale);


        $this->showCreateModal = false;

        // Dispatch the SendEmailNewTag job
        SendEmailNewTag::dispatch($tag->tag_id);


        $this->dispatch('tagCreated');
        $this->resetForm();

    }


    public function resetForm()
    {
        $this->reset([
            'showCreateModal',
            'createTag',
            'localeOptions',
            'categoryOptions',
            'categorySelected',
            'translationLanguages',
            'selectTranslationLanguage',
            'translateRadioButton',
            'selectTagTranslation'
        ]);

        $this->resetErrorBag();
    }


    public function render()
    {
        return view('livewire.tags.create');
    }
}
