<?php

namespace App\Modules\Admin\Tenancy\Services;

use App\Models\User;
use App\Modules\Admin\Operations\Repositories\PlatformAuditRepository;
use App\Modules\Admin\Tenancy\Models\Tenant;
use App\Modules\Admin\Tenancy\Repositories\TenantRepository;
use App\Modules\Admin\Tenancy\Support\TenantLifecycleState;
use Illuminate\Support\Facades\DB;

class TenantLifecycleService
{
    private const CAT = 'tenant_lifecycle';

    public function __construct(
        private readonly TenantRepository $tenants,
        private readonly PlatformAuditRepository $audit,
    ) {}

    public function suspend(Tenant $tenant, User $actor, string $reason): Tenant
    {
        return $this->transition($tenant, $actor, TenantLifecycleState::SUSPENDED, [
            'is_active' => false,
            'lifecycle_state' => TenantLifecycleState::SUSPENDED,
        ], $reason);
    }

    public function activate(Tenant $tenant, User $actor, string $reason): Tenant
    {
        return $this->transition($tenant, $actor, TenantLifecycleState::ACTIVE, [
            'is_active' => true,
            'lifecycle_state' => TenantLifecycleState::ACTIVE,
        ], $reason);
    }

    public function archive(Tenant $tenant, User $actor, string $reason): Tenant
    {
        return $this->transition($tenant, $actor, TenantLifecycleState::ARCHIVED, [
            'is_active' => false,
            'lifecycle_state' => TenantLifecycleState::ARCHIVED,
        ], $reason);
    }

    public function resumeFromSuspension(Tenant $tenant, User $actor, string $reason): Tenant
    {
        return $this->transition($tenant, $actor, TenantLifecycleState::ACTIVE, [
            'is_active' => true,
            'lifecycle_state' => TenantLifecycleState::ACTIVE,
        ], $reason);
    }

    public function syncGraceFromSubscription(int $tenantId): void
    {
        $t = $this->tenants->findWithPlan($tenantId);
        if ($t === null || in_array($t->lifecycle_state, [TenantLifecycleState::SUSPENDED, TenantLifecycleState::ARCHIVED], true)) {
            return;
        }
        if ($t->lifecycle_state !== TenantLifecycleState::GRACE_PERIOD) {
            $this->tenants->update($t, ['lifecycle_state' => TenantLifecycleState::GRACE_PERIOD]);
            $this->audit->record(null, $tenantId, self::CAT, 'synced.grace_from_subscription', []);
        }
    }

    public function syncActiveFromSubscription(int $tenantId): void
    {
        $t = $this->tenants->findWithPlan($tenantId);
        if ($t === null || in_array($t->lifecycle_state, [TenantLifecycleState::SUSPENDED, TenantLifecycleState::ARCHIVED], true)) {
            return;
        }
        if ($t->lifecycle_state === TenantLifecycleState::GRACE_PERIOD) {
            $this->tenants->update($t, ['lifecycle_state' => TenantLifecycleState::ACTIVE]);
            $this->audit->record(null, $tenantId, self::CAT, 'synced.active_after_grace', []);
        }
    }

    /**
     * @param  array<string, mixed>  $attrs
     */
    private function transition(Tenant $tenant, User $actor, string $toState, array $attrs, string $reason): Tenant
    {
        return DB::transaction(function () use ($tenant, $actor, $toState, $attrs, $reason): Tenant {
            $updated = $this->tenants->update($tenant, $attrs);
            $this->audit->record((int) $actor->id, (int) $tenant->id, self::CAT, 'transition.'.$toState, [
                'reason' => $reason,
                'from' => $tenant->lifecycle_state,
            ]);

            return $updated;
        });
    }
}
