<?php

namespace App\Filament\Resources\Users\Pages;

use App\Filament\Concerns\EnforcesPlanLimits;
use App\Filament\Resources\Users\UserResource;
use App\Models\User;
use App\Services\PlanLimitService;
use Filament\Actions\DeleteAction;
use Filament\Resources\Pages\EditRecord;
use Spatie\Permission\Models\Role;

class EditUser extends EditRecord
{
    use EnforcesPlanLimits;

    protected static string $resource = UserResource::class;

    // save + saveRelationships (sync de roles) en una transacción → el lock de
    // lockPlanForUpdate() serializa promociones concurrentes a cobrador (#169).
    protected ?bool $hasDatabaseTransactions = true;

    protected function getHeaderActions(): array
    {
        return [
            DeleteAction::make(),
        ];
    }

    /**
     * Aplica el cupo del plan también al EDITAR (#170): la guarda de `CreateUser`
     * no corría aquí, así que asignar el rol `collector` a un usuario existente
     * —o moverlo a otra empresa— superaba `max_collectors`/`max_users` sin control.
     *
     * Solo bloquea el "alta neta": asignar `collector` a quien no lo era, o mover
     * el usuario a otra empresa (donde cuenta como +1 usuario, y +1 cobrador si va
     * como cobrador). Editar a un cobrador que ya lo era, o cambiarle el nombre en
     * la misma empresa, no se bloquea aunque el cupo esté lleno.
     */
    protected function beforeSave(): void
    {
        $company = $this->planLimitCompany();
        $user = $this->record;

        if (! $company || ! $user instanceof User) {
            return; // super_admin sin empresa (company_id null)
        }

        $this->lockPlanForUpdate($company);

        $newCompanyId = (int) ($this->data['company_id'] ?? $user->company_id);
        $movedCompany = $newCompanyId !== (int) $user->getOriginal('company_id');

        $roleIds = array_map('intval', (array) ($this->data['roles'] ?? []));
        $willBeCollector = Role::whereKey($roleIds)->where('name', 'collector')->exists();
        // Rol persistido (aún no se sincroniza el del form en beforeSave).
        $wasCollector = $user->roles()->where('name', 'collector')->exists();

        $this->guardPlanLimit(function () use ($company, $movedCompany, $willBeCollector, $wasCollector): void {
            $service = app(PlanLimitService::class);

            if ($movedCompany) {
                // Entra a otra empresa → +1 usuario (y +1 cobrador si aplica).
                $service->assertCanAddUser($company);

                if ($willBeCollector) {
                    $service->assertCanAddCollector($company);
                }

                return;
            }

            // Misma empresa: solo es alta neta si se le AÑADE el rol cobrador.
            if ($willBeCollector && ! $wasCollector) {
                $service->assertCanAddCollector($company);
            }
        });
    }
}
