<?php

declare(strict_types=1);

namespace App\Services;

use App\Models\Company;
use App\Models\CompanyFinancialSettings;
use App\Models\Plan;
use App\Models\Subscription;
use App\Models\User;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Hash;
use RuntimeException;

/**
 * Auto-registro público con prueba de 14 días.
 *
 * Crea, en UNA transacción, todo lo que una empresa nueva necesita para operar
 * durante el trial: la Company, sus CompanyFinancialSettings por defecto, el
 * usuario admin, y una Subscription en estado `trial` sobre el plan público
 * (Profesional). El registro es NO autenticado, así que todo `company_id` se
 * fija explícitamente (MultiTenantScope no auto-setea sin sesión).
 *
 * El acceso durante el trial lo concede hasActiveSubscription() (status=trial +
 * ends_at futuro); al expirar, subscriptions:update-status lo pasa a grace/expired.
 */
class TrialRegistrationService
{
    /** Slug del único plan público ofrecido en el registro. */
    public const TRIAL_PLAN_SLUG = 'professional';

    /** Días de prueba por defecto si el plan no define trial_days. */
    public const DEFAULT_TRIAL_DAYS = 14;

    public function register(string $companyName, string $adminName, string $email, string $password): User
    {
        $plan = Plan::findBySlug(self::TRIAL_PLAN_SLUG);

        if (! $plan || ! $plan->is_active) {
            throw new RuntimeException('El plan de prueba no está disponible.');
        }

        return DB::transaction(function () use ($companyName, $adminName, $email, $password, $plan): User {
            $company = Company::create([
                'name' => $companyName,
                'email' => $email,
                'status' => Company::STATUS_ACTIVE,
                'interest_method' => Company::INTEREST_FLAT_RATE,
            ]);

            // Usuario admin de la empresa. company_id explícito (registro sin sesión).
            $user = new User;
            $user->company_id = $company->id;
            $user->name = $adminName;
            $user->email = $email;
            $user->password = Hash::make($password);
            $user->save();
            $user->assignRole('admin');

            // Settings financieros por defecto (created_by = el admin recién creado).
            CompanyFinancialSettings::forCompany($company->id)
                ->update(['created_by_user_id' => $user->id]);

            $trialDays = $plan->trial_days > 0 ? $plan->trial_days : self::DEFAULT_TRIAL_DAYS;
            $now = now();
            $endsAt = $now->copy()->addDays($trialDays);

            Subscription::create([
                'company_id' => $company->id,
                'plan_id' => $plan->id,
                'billing_cycle' => Subscription::BILLING_MONTHLY,
                'status' => Subscription::STATUS_TRIAL,
                'starts_at' => $now,
                'trial_ends_at' => $endsAt,
                'ends_at' => $endsAt,
            ]);

            return $user;
        });
    }
}
