<?php

namespace App\Modules\Admin\Tenancy\Services;

use App\Modules\Admin\Tenancy\DTOs\TenantData;
use App\Modules\Admin\Tenancy\Models\Plan;
use App\Modules\Admin\Tenancy\Models\Tenant;
use App\Modules\Admin\Tenancy\Repositories\PlanRepository;
use App\Modules\Admin\Tenancy\Repositories\TenantRepository;
use App\Modules\Admin\Tenancy\Support\TenantLifecycleState;
use Illuminate\Contracts\Pagination\LengthAwarePaginator;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;

class TenantService
{
    public function __construct(
        private readonly TenantRepository $repository,
        private readonly PlanRepository $planRepository,
        private readonly SubscriptionService $subscriptionService,
        private readonly UpgradePlanService $upgradePlanService,
    ) {}

    public function list(): Collection
    {
        return $this->repository->all();
    }

    public function paginateForIndex(Request $request): LengthAwarePaginator
    {
        return $this->repository->paginateForIndex($request);
    }

    public function create(TenantData $data): Tenant
    {
        return DB::transaction(function () use ($data) {
            $lifecycle = (string) config('tenancy.new_tenant_lifecycle', TenantLifecycleState::ACTIVE);
            if (! in_array($lifecycle, TenantLifecycleState::all(), true)) {
                $lifecycle = TenantLifecycleState::ACTIVE;
            }
            $tenant = $this->repository->create(array_merge($data->toArray(), [
                'lifecycle_state' => $lifecycle,
                'locale' => config('app.locale'),
                'timezone' => config('app.timezone'),
            ]));

            if ($data->planId !== null) {
                $plan = $this->planRepository->findWithModules($data->planId);
                if ($plan instanceof Plan) {
                    $this->subscriptionService->startFor($tenant, $plan);
                }
            }

            return $tenant->fresh(['plan', 'activeSubscription.plan']);
        });
    }

    public function update(Tenant $tenant, TenantData $data): Tenant
    {
        return DB::transaction(function () use ($tenant, $data) {
            $previousPlanId = $tenant->plan_id;
            $updated = $this->repository->update($tenant, $data->toArray());

            if ($data->planId !== null && $data->planId !== $previousPlanId) {
                $plan = $this->planRepository->findWithModules($data->planId);
                if ($plan instanceof Plan) {
                    $this->upgradePlanService->upgrade($updated, $plan);
                }
            }

            return $updated;
        });
    }

    public function delete(Tenant $tenant): void
    {
        $this->repository->delete($tenant);
    }
}
