<?php

namespace App\Filament\Resources;

use App\Filament\Exports\CustomerExporter;
use App\Filament\Resources\Concerns\HasModulePermissions;
use App\Filament\Resources\Concerns\HasStandardTableFeatures;
use App\Filament\Resources\CustomerResource\Pages\CreateCustomer;
use App\Filament\Resources\CustomerResource\Pages\EditCustomer;
use App\Filament\Resources\CustomerResource\Pages\ListCustomers;
use App\Filament\Resources\CustomerResource\Pages\ViewCustomer;
use App\Filament\Support\RelationSelect;
use App\Models\Customers\Customer;
use App\Models\Geo\City;
use App\Models\User;
use App\Services\AuditLog;
use App\Services\CurrentContext;
use Filament\Actions\Action;
use Filament\Actions\DeleteAction;
use Filament\Actions\EditAction;
use Filament\Forms\Components\Repeater;
use Filament\Forms\Components\Textarea;
use Filament\Forms\Components\TextInput;
use Filament\Forms\Components\Toggle;
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\Enums\FiltersLayout;
use Filament\Tables\Filters\Filter;
use Filament\Tables\Filters\SelectFilter;
use Filament\Tables\Filters\TernaryFilter;
use Filament\Tables\Table;
use Illuminate\Database\Eloquent\Builder;

/**
 * Ported from App\Http\Controllers\Isms\CustomerController
 * (docs/migration-plan.md Phase 8).
 *
 * Contacts and delivery addresses use Filament's native
 * `Repeater::relationship()` — the source's own sync loops already do an
 * id-aware update-or-create-then-delete-orphans diff, which is exactly what the
 * relationship repeater does out of the box (same reasoning as SupplierResource,
 * Decisions Log #21).
 *
 * Note these routes carry only their permission gate — unlike credit notes,
 * they are NOT wrapped in `customers_enabled`, so no PosSettings check applies.
 */
class CustomerResource extends Resource
{
    use HasModulePermissions;
    use HasStandardTableFeatures;

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

    protected static string $permissionModuleKey = 'isms_customers';

    protected static string $exporter = CustomerExporter::class;

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

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

    protected static ?int $navigationSort = 50;

    protected static ?string $recordTitleAttribute = 'business_name';

    public static function form(Schema $schema): Schema
    {
        return $schema->components([
            Section::make()->schema([
                TextInput::make('business_name')->required()->maxLength(200),
                TextInput::make('phone')->required()->maxLength(30),
                TextInput::make('nic')->label('NIC')->maxLength(20),
                TextInput::make('email')->email()->maxLength(150),
                TextInput::make('street_line1')->label('Street line 1')->maxLength(200),
                TextInput::make('street_line2')->label('Street line 2')->maxLength(200),
                RelationSelect::standalone(
                    name: 'city_id',
                    modelClass: City::class,
                    titleAttribute: 'name',
                )->label('City'),
                TextInput::make('legacy_city')->maxLength(100),
                RelationSelect::standalone(
                    name: 'assigned_user_id',
                    modelClass: User::class,
                    titleAttribute: 'name',
                )->label('Assigned user'),
                Toggle::make('is_active')->default(true),
            ])->columns(3),

            Section::make('Contacts')->schema([
                Repeater::make('contacts')
                    ->relationship()
                    ->schema([
                        TextInput::make('name')->required()->maxLength(200),
                        TextInput::make('phone')->required()->maxLength(30),
                    ])
                    ->columns(2)
                    ->defaultItems(0)
                    ->addActionLabel('Add contact')
                    ->columnSpanFull(),
            ]),

            Section::make('Delivery addresses')->schema([
                Repeater::make('deliveryAddresses')
                    ->relationship()
                    ->schema([
                        TextInput::make('label')->maxLength(100),
                        TextInput::make('street_line1')->label('Street line 1')->required()->maxLength(200),
                        TextInput::make('street_line2')->label('Street line 2')->maxLength(200),
                        RelationSelect::standalone(
                            name: 'city_id',
                            modelClass: City::class,
                            titleAttribute: 'name',
                        )->label('City'),
                        Textarea::make('note')->maxLength(300)->columnSpanFull(),
                    ])
                    ->columns(2)
                    ->defaultItems(0)
                    ->addActionLabel('Add address')
                    ->columnSpanFull(),
            ]),
        ]);
    }

    public static function table(Table $table): Table
    {
        return static::standardTableDefaults($table)
            ->recordUrl(static::standardRecordUrl())
            ->emptyStateHeading('No customers yet')
            ->emptyStateDescription('Customers added at the till or in the catalog will appear here.')
            ->modifyQueryUsing(fn (Builder $query): Builder => $query
                ->withCount('contacts')
                ->withSum('invoices as total_invoiced', 'net_total')
                ->withSum('invoices as total_paid', 'paid_amount')
                ->with('creditBalance:customer_id,balance'))
            ->columns([
                TextColumn::make('business_name')->label('Customer')->searchable()->sortable(),
                TextColumn::make('phone')->searchable(),
                TextColumn::make('nic')->label('NIC')->searchable()->placeholder('—')->toggleable(),
                TextColumn::make('email')->searchable()->placeholder('—')->toggleable(),
                TextColumn::make('city.name')->label('City')->placeholder('—')->toggleable(),
                TextColumn::make('contacts_count')->label('Contacts'),
                TextColumn::make('total_invoiced')->money(fn () => app(CurrentContext::class)->currencyCode())->placeholder('—'),
                TextColumn::make('total_paid')->money(fn () => app(CurrentContext::class)->currencyCode())->placeholder('—'),
                TextColumn::make('creditBalance.balance')->label('Credit')->money(fn () => app(CurrentContext::class)->currencyCode())->placeholder('—'),
                IconColumn::make('is_active')->boolean(),
            ])
            // Matches CustomerController::index()'s orderByDesc('is_active')->orderBy('business_name').
            ->defaultSort('is_active', 'desc')
            ->filters([
                Filter::make('business_name')
                    ->schema([TextInput::make('value')->label('Customer')])
                    ->query(fn (Builder $query, array $data): Builder => $query->when(
                        $data['value'] ?? null,
                        fn (Builder $q, $value) => $q->where('business_name', 'like', "%{$value}%"),
                    )),
                Filter::make('phone')
                    ->schema([TextInput::make('value')->label('Phone')])
                    ->query(fn (Builder $query, array $data): Builder => $query->when(
                        $data['value'] ?? null,
                        fn (Builder $q, $value) => $q->where('phone', 'like', "%{$value}%"),
                    )),
                Filter::make('nic')
                    ->schema([TextInput::make('value')->label('NIC')])
                    ->query(fn (Builder $query, array $data): Builder => $query->when(
                        $data['value'] ?? null,
                        fn (Builder $q, $value) => $q->where('nic', 'like', "%{$value}%"),
                    )),
                Filter::make('email')
                    ->schema([TextInput::make('value')->label('Email')])
                    ->query(fn (Builder $query, array $data): Builder => $query->when(
                        $data['value'] ?? null,
                        fn (Builder $q, $value) => $q->where('email', 'like', "%{$value}%"),
                    )),
                SelectFilter::make('city_id')->label('City')->relationship('city', 'name'),
                TernaryFilter::make('is_active')->label('Active'),
            ])
            ->filtersLayout(FiltersLayout::AboveContentCollapsible)
            ->filtersFormColumns(2)
            ->headerActions(static::standardExportActions())
            ->toolbarActions(static::standardExportBulkActions())
            ->recordActions([
                Action::make('view')
                    ->url(fn (Customer $record): string => ViewCustomer::getUrl(['record' => $record]))
                    ->visible(fn (Customer $record): bool => static::canView($record)),
                EditAction::make(),
                // CustomerController::destroy() records the audit entry before
                // the delete, while the row is still readable.
                DeleteAction::make()
                    ->before(function (Customer $record): void {
                        AuditLog::record('customer.deleted', $record, ['name' => $record->business_name]);
                    }),
            ]);
    }

    public static function getPages(): array
    {
        return [
            'index' => ListCustomers::route('/'),
            'create' => CreateCustomer::route('/create'),
            'view' => ViewCustomer::route('/{record}'),
            'edit' => EditCustomer::route('/{record}/edit'),
        ];
    }
}
