<?php

namespace App\Filament\Resources;

use App\Filament\Clusters\AdManagement;
use App\Filament\Resources\AdResource\Pages;
use App\Filament\Resources\AdResource\RelationManagers;
use App\Models\Ad;
use App\Models\AdCondition;
use App\Models\Category;
use App\Models\CategoryField;
use App\Models\City;
use App\Models\Country;
use App\Models\PriceType;
use App\Models\State;
use App\Models\User;
use App\Settings\AdSettings;
use App\Settings\GeneralSettings;
use Closure;
use Filament\Tables\Actions\Action;
use Filament\Forms;
use Filament\Forms\Components\Grid;
use Filament\Forms\Components\KeyValue;
use Filament\Forms\Components\MarkdownEditor;
use Filament\Forms\Components\Select;
use Filament\Forms\Components\SpatieMediaLibraryFileUpload;
use Filament\Forms\Components\TagsInput;
use Filament\Forms\Components\TextInput;
use Filament\Forms\Components\ToggleButtons;
use Filament\Forms\Form;
use Filament\Forms\Get;
use Filament\Forms\Set;
use Filament\Notifications\Notification;
use Filament\Resources\Resource;
use Filament\Tables;
use Filament\Tables\Actions\BulkActionGroup;
use Filament\Tables\Actions\DeleteAction;
use Filament\Tables\Actions\DeleteBulkAction;
use Filament\Tables\Columns\ImageColumn;
use Filament\Tables\Columns\SelectColumn;
use Filament\Tables\Columns\TextColumn;
use Filament\Tables\Table;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\SoftDeletingScope;
use Filament\Tables\Columns\SpatieMediaLibraryImageColumn;
use Illuminate\Support\HtmlString;
use Ysfkaya\FilamentPhoneInput\Forms\PhoneInput;
use Filament\Forms\Components\{Checkbox, DatePicker, DateTimePicker, Radio, Section, TimePicker, Textarea};


class AdResource extends Resource
{
    protected static ?string $model = Ad::class;

    protected static ?string $cluster = AdManagement::class;

    protected static ?string $navigationIcon = 'heroicon-o-list-bullet';

    public static function canAccess(): bool
    {
        return userHasPermission('view_ad');
    }

    public static function canCreate(): bool
    {
        return userHasPermission('create_ad');
    }

    public static function canEdit($record): bool
    {
        return userHasPermission('update_ad');
    }

    public static function canDelete($record): bool
    {
        return userHasPermission('delete_ad');
    }

    public static function getModelLabel(): string
    {
        return __('messages.t_ap_ad');
    }

    public static function getNavigationLabel(): string
    {
        return __('messages.t_ap_ad_all');
    }

    protected static function getFieldTemplateMappings($categoryId)
    {
        $templateFieldRecord = Category::whereId($categoryId)->with('fieldTemplate.fieldTemplateMappings.field')->first();
        $templateFields = $templateFieldRecord?->fieldTemplate?->fieldTemplateMappings?->sortBy('order') ?? collect([]);
        return $templateFields;
    }

    protected static function getFieldsForAd($categoryId)
    {
        if (!$categoryId)
            return collect([]);

        if ($categoryId) {
            //Sub category Fields
            $categoryFields = CategoryField::where('category_id', $categoryId)
                ->with('field')
                ->get();
            $subCategoryFields = static::getFieldTemplateMappings($categoryId);
            //get main Category
            $mainCategory = Category::whereHas('subcategories', fn($query) => $query->whereId($categoryId))->first();
            //Sub category Fields
            $mainCategoryFields = $mainCategory ? static::getFieldTemplateMappings($mainCategory->id) : collect([]);
            //return subcategory if not exist then return main category if not exits the normal dynamic fields
            return count($subCategoryFields) ? $subCategoryFields : (count($mainCategoryFields) ? $mainCategoryFields : $categoryFields);
        }
    }

    /**
     * Map fields to form components.
     */
    protected static function mapFieldsToComponents($fieldData)
    {
        $components = [];
        $fieldData = is_null($fieldData) ? collect([]) : $fieldData;
        $fieldGroup = collect([]);
        $finalField = $fieldData->map(function ($field) use (&$components, &$fieldGroup) {
            if ($field && $field->field) {
                // Get the name of the fieldGroup
                $groupName = $field?->field?->fieldGroup?->name ?? '';
                // Push the field to the corresponding group in $fieldGroup
                if (!$fieldGroup->has($groupName)) {
                    $fieldGroup[$groupName] = collect([]);
                }
                $fieldGroup[$groupName]->push($field->field);
            }
        });
        foreach ($fieldGroup as $groupName => $fields) {
            $sectionComponents = [];
            foreach ($fields->sortBy('order') as $field) {
                // Check if the field relationship is not null
                if (!$field) {
                    // Skip this iteration if the field is null
                    continue;
                }
                $dynamicFieldId = 'dynamic_' . $field->id;
                $fieldType = $field->type->value;
                switch ($fieldType) {
                    case 'text':
                        ${strlen($groupName) ? 'sectionComponents' : 'components'}[] = TextInput::make($dynamicFieldId)->label($field->name)->label($field->name)->required($field->required)->live(onBlur: true)->helperText($field->helpertext);
                        break;
                    case 'select':
                        ${strlen($groupName) ? 'sectionComponents' : 'components'}[] = Select::make($dynamicFieldId)->label($field->name)->options($field->options)->required($field->required)->live(onBlur: true)->helperText($field->helpertext);
                        break;
                    case 'checkbox':
                        ${strlen($groupName) ? 'sectionComponents' : 'components'}[] = Checkbox::make($dynamicFieldId)->label($field->name)->required($field->required)->live(onBlur: true)->helperText($field->helpertext);
                        break;

                    case 'radio':
                        ${strlen($groupName) ? 'sectionComponents' : 'components'}[] = Radio::make($dynamicFieldId)->label($field->name)->options($field->options)->required($field->required)->live(onBlur: true)->helperText($field->helpertext);
                        break;
                    case 'datetime':
                        ${strlen($groupName) ? 'sectionComponents' : 'components'}[] = DateTimePicker::make($dynamicFieldId)->label($field->name)->required($field->required)->live(onBlur: true)->helperText($field->helpertext);
                        break;
                    case 'date':
                        ${strlen($groupName) ? 'sectionComponents' : 'components'}[] = DatePicker::make($dynamicFieldId)->label($field->name)->required($field->required)->live(onBlur: true)->helperText($field->helpertext);
                        break;
                    case 'time':
                        ${strlen($groupName) ? 'sectionComponents' : 'components'}[] = TimePicker::make($dynamicFieldId)->label($field->name)->required($field->required)->live(onBlur: true)->helperText($field->helpertext);
                        break;
                    case 'textarea':
                        ${strlen($groupName) ? 'sectionComponents' : 'components'}[] = Textarea::make($dynamicFieldId)->label($field->name)->required($field->required)->live(onBlur: true)->helperText($field->helpertext);
                        break;
                    case 'tagsinput':
                        ${strlen($groupName) ? 'sectionComponents' : 'components'}[] = TagsInput::make($dynamicFieldId)->label($field->name)->required($field->required)->live(onBlur: true)->helperText($field->helpertext);
                        break;
                    case 'number':
                        ${strlen($groupName) ? 'sectionComponents' : 'components'}[] = TextInput::make($dynamicFieldId)->numeric()->label($field->name)->required($field->required)->live(onBlur: true)->helperText($field->helpertext);
                        break;
                }
            }
            if (count($sectionComponents))
                $components[] = Section::make($groupName)->schema($sectionComponents)->collapsible()->collapsible();
        }
        return $components;
    }

    public static function form(Form $form): Form
    {
        $adSettings = app(AdSettings::class);
        return $form
            ->schema([
                TextInput::make('title')
                    ->label(__('messages.t_ap_title'))
                    ->live(onBlur: true)
                    ->placeholder(__('messages.t_ap_what_are_you_selling'))
                    ->minLength(10)
                    ->required(),

                Select::make('main_category_id')
                    ->label(__('messages.t_ap_main_category'))
                    ->options(Category::whereNull('parent_id')->pluck('name', 'id'))
                    ->live()
                    ->required()
                    ->dehydrated()
                    ->placeholder(__('messages.t_ap_select_main_category')),

                Select::make('category_id')
                    ->label(__('messages.t_ap_sub_category'))
                    ->options(function (Get $get) {
                        $mainCategoryId = $get('main_category_id');
                        return Category::where('parent_id', $mainCategoryId)->pluck('name', 'id');
                    })
                    ->live()
                    ->required()
                    ->hidden(fn(Get $get): bool => !$get('main_category_id'))
                    ->placeholder(__('messages.t_ap_select_sub_category')),

                ToggleButtons::make('for_sale_by')
                    ->label(__('messages.t_ap_for_sale_by'))
                    ->live()
                    ->required()
                    ->grouped()
                    ->options([
                        'owner' => __('messages.t_ap_owner_for_sale'),
                        'business' => __('messages.t_ap_business_for_sale'),
                    ]),

                MarkdownEditor::make('description')
                    ->disableToolbarButtons([
                        'attachFiles'
                    ])
                    ->label(__('messages.t_ap_description'))
                    ->live(onBlur: true)
                    ->minLength(20)
                    ->required(),

                ToggleButtons::make('condition_id')
                    ->label(__('messages.t_ap_condition'))
                    ->live()
                    ->options(AdCondition::all()->pluck('name', 'id'))
                    ->inline(),

                Select::make('user_id')
                    ->label(__('messages.t_ap_posted_by'))
                    ->options(User::all()->pluck('name', 'id'))
                    ->live()
                    ->required()
                    ->placeholder(__('messages.t_ap_select_a_user')),

                Select::make('price_type_id')
                    ->label(__('messages.t_ap_price'))
                    ->live()
                    ->required()
                    ->options(PriceType::all()->pluck('name', 'id')),

                TextInput::make('price')
                    ->helperText(__('messages.t_ap_set_fair_price'))
                    ->required()
                    ->numeric()
                    ->minValue(1)
                    ->placeholder(__('messages.t_ap_price_your_ad'))
                    ->prefix(config('app.currency_symbol'))
                    ->live(onBlur: true)
                    ->hidden(fn(Get $get): bool => $get('price_type_id') != 1)
                    ->hiddenLabel(),

                ToggleButtons::make('display_phone')
                    ->label(__('messages.t_display_phone_number'))
                    ->live()
                    ->boolean()
                    ->grouped(),

                PhoneInput::make('phone_number')
                    ->initialCountry(app(GeneralSettings::class)->default_mobile_country ?? 'us')
                    ->placeholder(__('messages.t_enter_phone_number'))
                    ->helperText(__('messages.t_phone_number_helper'))
                    ->required()
                    ->live()
                    ->hidden(fn(Get $get): bool => !$get('display_phone'))
                    ->hiddenLabel(),

                ToggleButtons::make('display_whatsapp')
                    ->label(__('messages.t_display_whatsapp_number'))
                    ->live()
                    ->boolean()
                    ->grouped(),

                PhoneInput::make('whatsapp_number')
                    ->initialCountry(app(GeneralSettings::class)->default_mobile_country ?? 'us')
                    ->placeholder(__('messages.t_enter_phone_number'))
                    ->helperText(__('messages.t_display_whatsapp_helper_text'))
                    ->live()
                    ->required()
                    ->hidden(fn(Get $get): bool => !$get('display_whatsapp'))
                    ->hiddenLabel(),
                Grid::make(2)->schema(function (Get $get) {
                    return self::mapFieldsToComponents(self::getFieldsForAd($get('category_id')));
                }),

                TagsInput::make('tags')
                    ->label(__('messages.t_ap_tags'))
                    ->helperText(__('messages.t_ap_set_tags'))
                    ->live(onBlur: true),

                SpatieMediaLibraryFileUpload::make('ads')
                    ->maxSize(maxUploadFileSize())
                    ->label(__('messages.t_ap_upload_photos'))
                    ->multiple()
                    ->collection('ads')
                    ->required()
                    ->minFiles(1)
                    ->maxFiles($adSettings->image_limit)
                    ->rules([
                        function () {
                            return function (string $attribute, $value, Closure $fail) {
                                $originalName = $value->getClientOriginalName();
                                $maxLength = 191;
                                if (!mb_detect_encoding($originalName)) {
                                    $fail("The file name is too long. Maximum length allowed is {$maxLength} characters.");
                                    Notification::make()
                                        ->title("The file name is too long. Maximum length allowed is {$maxLength} characters.")
                                        ->danger()
                                        ->send();
                                }
                            };
                        },
                    ])
                    ->openable()
                    ->imageEditor()
                    ->imageResizeMode('cover')
                    ->reorderable()
                    ->helperText(__('messages.t_ap_add_photos_to_ad', ['image_limit' => $adSettings->image_limit]))
                    ->appendFiles(),

                KeyValue::make('image_properties')
                    ->keyLabel(__('messages.t_ap_image_order'))
                    ->visible(fn(): bool => $adSettings->allow_image_alt_tags)
                    ->keyPlaceholder(__('messages.t_ap_enter_image_id'))
                    ->valueLabel(__('messages.t_ap_alt_text'))
                    ->valuePlaceholder(__('messages.t_ap_enter_alt_text'))
                    ->addable(false)
                    ->live(onBlur: true)
                    ->deletable(false)
                    ->editableKeys(false)
                    ->helperText(__('messages.t_ap_provide_descriptive_alt_text'))
                    ->editableValues(true),

                TextInput::make('video_link')
                    ->label(__('messages.t_ap_youtube_video_link'))
                    ->url()
                    ->live(onBlur: true)
                    ->suffixIcon('heroicon-m-video-camera')
                    ->placeholder(__('messages.t_ap_example_youtube_link'))
                    ->hint(__('messages.t_ap_add_youtube_video_hint')),

                Select::make('country_id')
                    ->label(__('messages.t_ap_country'))
                    ->options(Country::pluck('name', 'id')->toArray())
                    ->live()
                    ->afterStateUpdated(fn(callable $set) => $set('state_id', null))
                    ->required(),

                Select::make('state_id')
                    ->label(__('messages.t_ap_state'))
                    ->options(function (Get $get) {
                        $countryId = $get('country_id');
                        if (!$countryId) {
                            return [];
                        }
                        return State::where('country_id', $countryId)->pluck('name', 'id')->toArray();
                    })
                    ->live()
                    ->hidden(fn(Get $get): bool => !$get('country_id'))
                    ->afterStateUpdated(fn(callable $set) => $set('city_id', null))
                    ->required(),

                Select::make('city_id')
                    ->label(__('messages.t_ap_city'))
                    ->options(function (Get $get) {
                        $stateId = $get('state_id');
                        if (!$stateId) {
                            return [];
                        }
                        return City::where('state_id', $stateId)->pluck('name', 'id')->toArray();
                    })
                    ->hidden(fn(Get $get): bool => !$get('state_id'))
                    ->required()

            ])
            ->columns(1);
    }

    public static function table(Table $table): Table
    {
        return $table
            ->modifyQueryUsing(fn(Builder $query) => $query->latest())
            ->columns([
                SpatieMediaLibraryImageColumn::make('ads')
                    ->collection('ads')
                    ->conversion('thumb')
                    ->defaultImageUrl(fn($record)=>getAdPlaceholderImage($record->id))
                    ->label(__('messages.t_ap_ad_images'))
                    ->size(40)
                    ->circular()
                    ->overlap(2)
                    ->stacked()
                    ->limit(3),

                TextColumn::make('title')
                    ->searchable()
                    ->label(__('messages.t_ap_title')),

                TextColumn::make('view_count')
                    ->label(__('messages.t_ap_views'))
                    ->sortable(),

                TextColumn::make('likes_count')
                    ->label(__('messages.t_ap_likes')),

                TextColumn::make('user.name')
                    ->label(__('messages.t_ap_posted_by'))
                    ->sortable(),

                TextColumn::make('price')
                    ->label(__('messages.t_ap_price')),

                TextColumn::make('location_name')
                    ->label(__('messages.t_ap_location')),

                TextColumn::make('posted_date')
                    ->label(__('messages.t_ap_posted_on'))
                    ->date(),

                TextColumn::make('category.name')
                    ->label(__('messages.t_ap_category'))
                    ->sortable(),

                SelectColumn::make('status')
                    ->options([
                        'draft' => __('messages.t_ap_draft'),
                        'active' => __('messages.t_ap_active'),
                        'inactive' => __('messages.t_ap_inactive'),
                        'sold' => __('messages.t_ap_sold'),
                    ])
                    ->label(__('messages.t_ap_change_status'))
                    ->selectablePlaceholder(false),

            ])
            ->defaultSort('posted_date', 'desc')
            ->filters([
                Tables\Filters\TrashedFilter::make(),
            ])
            ->actions([
                Tables\Actions\EditAction::make(),
                Action::make('view')
                    ->icon('heroicon-o-eye')
                    ->label(__('messages.t_ap_view_details'))
                    ->url(fn(Ad $record): string => route('ad.overview', $record->slug))
                    ->openUrlInNewTab(),
                Tables\Actions\DeleteAction::make(),
                Tables\Actions\RestoreAction::make(),
                Tables\Actions\ForceDeleteAction::make(),
            ])
            ->bulkActions([
                BulkActionGroup::make([
                    Tables\Actions\DeleteBulkAction::make(),
                    Tables\Actions\RestoreBulkAction::make(),
                    Tables\Actions\ForceDeleteBulkAction::make(),
                ]),
            ]);
    }

    public static function getRelations(): array
    {
        return [
            //
        ];
    }

    public static function getPages(): array
    {
        return [
            'index' => Pages\ListAds::route('/'),
            'create' => Pages\CreateAd::route('/create'),
            'edit' => Pages\EditAd::route('/{record}/edit')
        ];
    }
}
