<?php

namespace App\Filament\Resources;

use App\Filament\Resources\Concerns\HasModulePermissions;
use App\Filament\Resources\Concerns\HasStandardTableFeatures;
use App\Filament\Resources\MainCategoryResource\Pages\CreateMainCategory;
use App\Filament\Resources\MainCategoryResource\Pages\EditMainCategory;
use App\Filament\Resources\MainCategoryResource\Pages\ListMainCategories;
use App\Models\Catalog\MainCategory;
use App\Services\AuditLog;
use App\Support\SortCodeGenerator;
use Filament\Actions\DeleteAction;
use Filament\Actions\EditAction;
use Filament\Forms\Components\Textarea;
use Filament\Forms\Components\TextInput;
use Filament\Forms\Components\Toggle;
use Filament\Notifications\Notification;
use Filament\Resources\Resource;
use Filament\Schemas\Components\Section;
use Filament\Schemas\Schema;
use Filament\Support\Icons\Heroicon;
use Filament\Tables\Columns\IconColumn;
use Filament\Tables\Columns\TextColumn;
use Filament\Tables\Filters\TernaryFilter;
use Filament\Tables\Table;
use Illuminate\Database\Eloquent\Model;

/**
 * Ported from App\Http\Controllers\Isms\MainCategoryController
 * (docs/migration-plan.md Phase 2). sort_code is server-generated
 * (SortCodeGenerator, same algorithm as the source controller's private
 * generateSortCode()), never user-editable — matches the source app, which
 * never exposes it on the create/edit forms either.
 */
class MainCategoryResource extends Resource
{
    use HasModulePermissions;
    use HasStandardTableFeatures;

    protected static ?string $model = MainCategory::class;

    protected static string $permissionModuleKey = 'isms_main_categories';

    protected static string|\BackedEnum|null $navigationIcon = Heroicon::OutlinedRectangleStack;

    protected static string|\UnitEnum|null $navigationGroup = 'Master Data';

    protected static ?string $navigationLabel = 'Main Categories';

    protected static ?int $navigationSort = 10;

    /**
     * A system category is undeletable for everyone, permission or not —
     * {@see MainCategory::delete()} enforces the same rule at the model.
     */
    public static function canDelete(Model $record): bool
    {
        return ! $record->is_system && static::hasModulePermission('delete');
    }

    public static function form(Schema $schema): Schema
    {
        return $schema->components([
            Section::make()->schema([
                TextInput::make('name')
                    ->required()
                    ->maxLength(100)
                    ->unique(ignoreRecord: true)
                    // MainCategory rejects a rename of a system row outright;
                    // disabling the field says so before the save rather than
                    // after it.
                    ->disabled(fn (?MainCategory $record): bool => (bool) $record?->is_system)
                    ->helperText(fn (?MainCategory $record): ?string => $record?->is_system
                        ? 'System category — its name is fixed.'
                        : null),
                Textarea::make('description')
                    ->maxLength(500)
                    ->columnSpanFull(),
                Toggle::make('is_active')
                    ->default(true),
            ]),
        ]);
    }

    public static function table(Table $table): Table
    {
        return static::standardTableDefaults($table)
            ->recordUrl(static::standardRecordUrl())
            ->emptyStateHeading('No main categories yet')
            ->emptyStateDescription('Group your products into categories to keep the catalog tidy.')
            ->columns([
                TextColumn::make('name')->searchable()->sortable(),
                TextColumn::make('sort_code')->label('Code')->badge(),
                TextColumn::make('sub_categories_count')->label('Sub-categories')->counts('subCategories'),
                TextColumn::make('products_count')->label('Products')->counts('products'),
                IconColumn::make('is_system')->boolean()->label('System'),
                IconColumn::make('is_active')->boolean()->label('Active'),
            ])
            ->filters([
                TernaryFilter::make('is_active')->label('Active'),
            ])
            ->defaultSort('is_active', 'desc')
            ->recordActions([
                EditAction::make(),
                DeleteAction::make()
                    ->hidden(fn (MainCategory $record): bool => $record->is_system)
                    ->before(function (MainCategory $record, DeleteAction $action): void {
                        if ($record->products()->exists()) {
                            Notification::make()
                                ->title('Cannot delete: category has products.')
                                ->danger()
                                ->send();
                            $action->cancel();
                        }
                    })
                    ->after(fn (MainCategory $record) => AuditLog::record('main_category.deleted', $record, [
                        'name' => $record->name,
                        'description' => 'Deleted main category "'.$record->name.'".',
                    ])),
            ]);
    }

    public static function getPages(): array
    {
        return [
            'index' => ListMainCategories::route('/'),
            'create' => CreateMainCategory::route('/create'),
            'edit' => EditMainCategory::route('/{record}/edit'),
        ];
    }

    public static function generateSortCode(string $name): string
    {
        return SortCodeGenerator::generate(MainCategory::class, $name, 'CAT');
    }
}
