<?php

declare(strict_types=1);

namespace App\Filament\Resources\Concerns;

use App\Business\MasterData\DberpRegionAddressService;
use App\Models\DberpRegion;
use Filament\Forms\Components\Hidden;
use Filament\Forms\Components\Select;
use Filament\Forms\Components\TextInput;
use Filament\Schemas\Components\Component;
use Filament\Schemas\Components\Section;
use Filament\Schemas\Components\Utilities\Get;
use Filament\Schemas\Components\Utilities\Set;
use Filament\Tables\Columns\TextColumn;
use Filament\Tables\Filters\SelectFilter;

trait HasDberpRegionAddress
{
    protected static function getDberpRegionAddressSection(bool $withHelperTexts = true): Section
    {
        $section = Section::make(__('dberp.sections.region_address'))
            ->schema(static::getDberpRegionAddressFormFields($withHelperTexts))
            ->columns(2);

        if ($withHelperTexts) {
            $section
                ->description(__('dberp.hints.region_selection_scope'));
        }

        return $section;
    }

    /**
     * @return array<int, Component>
     */
    protected static function getDberpRegionAddressFormFields(bool $withHelperTexts = true): array
    {
        /** @var DberpRegionAddressService $service */
        $service = app(DberpRegionAddressService::class);

        $fields = [];

        if ($service->shouldOfferCountryChoice()) {
            $country = Select::make('country_code')
                ->label(__('dberp.fields.country'))
                ->options($service->countryOptions())
                ->default($service->defaultCountryCode())
                ->live()
                ->afterStateUpdated(function (Set $set): void {
                    $set('province_region_id', null);
                    $set('city_region_id', null);
                    $set('district_region_id', null);
                });

            if ($withHelperTexts) {
                $country->helperText(__('dberp.hints.region_default_country'));
            }

            $fields[] = $country;
        } elseif (filled($service->defaultCountryCode())) {
            $defaultCountryCode = (string) $service->defaultCountryCode();

            $fields[] = Hidden::make('country_code')
                ->default($defaultCountryCode)
                ->dehydrated()
                ->afterStateHydrated(function (Hidden $component, $state) use ($defaultCountryCode): void {
                    if (! filled($state)) {
                        $component->state($defaultCountryCode);
                    }
                });
        }

        $province = Select::make('province_region_id')
            ->label(__('dberp.fields.province_region'))
            ->options(fn (Get $get): array => app(DberpRegionAddressService::class)->provinceOptions($get('country_code'), filled($get('province_region_id')) ? (int) $get('province_region_id') : null))
            ->searchable()
            ->preload()
            ->live()
            ->dehydrated(false)
            ->visible(fn (Get $get): bool => filled($get('country_code')))
            ->afterStateUpdated(function (Set $set): void {
                $set('city_region_id', null);
                $set('district_region_id', null);
            });

        $city = Select::make('city_region_id')
            ->label(__('dberp.fields.city_region'))
            ->options(fn (Get $get): array => app(DberpRegionAddressService::class)->cityOptions($get('province_region_id'), filled($get('city_region_id')) ? (int) $get('city_region_id') : null))
            ->searchable()
            ->preload()
            ->live()
            ->dehydrated(false)
            ->visible(fn (Get $get): bool => filled($get('province_region_id')))
            ->afterStateUpdated(function (Set $set): void {
                $set('district_region_id', null);
            });

        $district = Select::make('district_region_id')
            ->label(__('dberp.fields.master_data_region_district'))
            ->options(fn (Get $get): array => app(DberpRegionAddressService::class)->districtOptions($get('city_region_id'), filled($get('district_region_id')) ? (int) $get('district_region_id') : null))
            ->searchable()
            ->preload()
            ->live()
            ->dehydrated(true)
            ->visible(fn (Get $get): bool => filled($get('city_region_id')));

        $address = TextInput::make('address')
            ->label(__('dberp.fields.address_detail'))
            ->maxLength(255)
            ->columnSpanFull();

        if ($withHelperTexts) {
            $address->helperText(__('dberp.hints.address_detail'));
        }

        return [
            ...$fields,
            $province,
            $city,
            $district,
            $address,
        ];
    }

    /**
     * @return array<int, TextColumn>
     */
    protected static function getDberpRegionAddressTableColumns(): array
    {
        return [
            TextColumn::make('country_code')
                ->label(__('dberp.fields.country'))
                ->formatStateUsing(fn (?string $state): string => app(DberpRegionAddressService::class)->formatCountryLabel($state))
                ->toggleable(isToggledHiddenByDefault: true),
            TextColumn::make('region_name_snapshot')
                ->label(__('dberp.sections.region_address'))
                ->state(fn ($record): string => app(DberpRegionAddressService::class)->formatRegionAddressSummary($record->country_code, $record->region_name_snapshot, $record->address, $record->region))
                ->wrap()
                ->searchable(),
            TextColumn::make('address')
                ->label(__('dberp.fields.address_detail'))
                ->placeholder(__('dberp.messages.address_detail_not_set'))
                ->toggleable(isToggledHiddenByDefault: true),
        ];
    }

    /**
     * @return array<int, SelectFilter>
     */
    protected static function getDberpRegionCountryFilters(): array
    {
        if (! app(DberpRegionAddressService::class)->shouldOfferCountryChoice()) {
            return [];
        }

        return [
            SelectFilter::make('country_code')
                ->label(__('dberp.fields.country'))
                ->options(app(DberpRegionAddressService::class)->countryOptions()),
        ];
    }

    protected static function getDberpRegionDisplay(?string $regionSnapshot, ?DberpRegion $region): string
    {
        return app(DberpRegionAddressService::class)->formatRegionLabel($regionSnapshot, $region);
    }
}
