<?php

namespace App\Filament\Central\Resources\TenantResource\Pages;

use App\Filament\Central\Resources\TenantResource;
use App\Models\Central\Tenant;
use App\Services\Tenancy\TenantProvisioner;
use App\Services\Tenancy\TestInstanceService;
use Filament\Actions\Action;
use Filament\Notifications\Notification;
use Filament\Resources\Pages\CreateRecord;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Str;

/**
 * Ported from TenantController::store(). Creates the tenant row then hands off
 * to TenantProvisioner, which grants the full entitlement set, seeds the
 * tenant-scoped lookups and system roles, creates the first branch and the
 * owner account, and returns that account's generated password.
 *
 * The source flashes those credentials into the session for the show page to
 * display once; here they are surfaced in a persistent notification, which is
 * the same "show it exactly once, never store it" behaviour.
 *
 * The "Enable Test Instance" toggle (see TenantResource::form) provisions an
 * isolated test copy of the tenant alongside the live one (its own subdomain,
 * e.g. "acme-test"), seeded with the freshly provisioned live state.
 */
class CreateTenant extends CreateRecord
{
    protected static string $resource = TenantResource::class;

    /**
     * One primary action for the whole form: provision the tenant and its
     * owner account in a single step.
     */
    protected function getCreateFormAction(): Action
    {
        return parent::getCreateFormAction()->label('Create & Provision');
    }

    protected function handleRecordCreation(array $data): Tenant
    {
        $tenant = Tenant::create([
            'name' => $data['name'],
            'slug' => Str::lower($data['slug']),
            'status' => Tenant::STATUS_ACTIVE,
        ]);

        $result = app(TenantProvisioner::class)->provision($tenant, [
            'name' => $data['admin_name'],
            'email' => $data['admin_email'],
        ]);

        TenantResource::audit($tenant, 'tenant.provisioned', ['admin_email' => $data['admin_email']]);

        $this->notifyProvisioned($result);

        if (($data['enable_test_instance'] ?? false) === true) {
            $this->provisionTestInstance($tenant);
        }

        return $tenant;
    }

    /**
     * @param  array{tenant: Tenant, owner: \App\Models\User, password: string}  $result
     */
    private function notifyProvisioned(array $result): void
    {
        Notification::make()
            ->title('Tenant provisioned')
            ->body(sprintf(
                'Administrator %s (%s) — temporary password: %s',
                $result['owner']->name,
                $result['owner']->email,
                $result['password'],
            ))
            ->success()
            ->persistent()
            ->send();
    }

    private function provisionTestInstance(Tenant $tenant): void
    {
        try {
            $test = app(TestInstanceService::class)->create($tenant, Auth::guard('central')->id());
        } catch (\Throwable $e) {
            Notification::make()
                ->title('Test instance could not be created')
                ->body($e->getMessage().' The live tenant itself was provisioned successfully.')
                ->danger()
                ->persistent()
                ->send();

            return;
        }

        TenantResource::audit($tenant, 'tenant.test_instance_provisioned', [
            'test_tenant_id' => $test->id,
            'test_slug' => $test->slug,
        ]);

        Notification::make()
            ->title('Test instance provisioned')
            ->body(sprintf(
                'Isolated copy ready on "%s". It was seeded with the current live state.',
                $test->url(),
            ))
            ->success()
            ->persistent()
            ->send();
    }

    protected function getRedirectUrl(): string
    {
        return TenantResource::getUrl('index');
    }
}