<?php

namespace App\Http\Controllers\Public;

use App\Http\Controllers\Controller;
use App\Enums\CompanyStatus;
use App\Enums\SubscriptionStatus;
use App\Enums\UserRole;
use App\Models\Company;
use App\Models\Plan;
use App\Models\Subscription;
use App\Models\SubscriptionPayment;
use App\Models\User;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Str;
use Illuminate\Validation\Rules;
use Illuminate\View\View;
use Spatie\Permission\Models\Role;

class PricingController extends Controller
{
    public function index(Request $request): View
    {
        $plans = Plan::where('is_active', true)
            ->where('is_public', true)
            ->orderBy('sort_order')
            ->get();

        $selectedPlan = null;
        if ($request->filled('plan')) {
            $selectedPlan = $plans->firstWhere('slug', $request->query('plan'))
                ?? Plan::where('is_active', true)
                    ->where('is_public', true)
                    ->whereKey($request->query('plan'))
                    ->first();
        }

        return view('public.pricing', compact('plans', 'selectedPlan'));
    }

    public function checkout(Request $request): RedirectResponse
    {
        $data = $request->validate([
            'plan_id' => ['required', 'exists:plans,id'],
            'billing_cycle' => ['required', 'in:monthly,yearly'],
            'company_name' => ['required', 'string', 'max:255'],
            'company_phone' => ['nullable', 'string', 'max:30'],
            'company_email' => ['required', 'email', 'max:255'],
            'company_address' => ['nullable', 'string', 'max:255'],
            'company_country' => ['required', 'string', 'max:100'],
            'company_city' => ['required', 'string', 'max:100'],
            'admin_first_name' => ['required', 'string', 'max:120'],
            'admin_last_name' => ['required', 'string', 'max:120'],
            'admin_email' => ['required', 'email', 'max:255', 'unique:users,email'],
            'password' => ['required', 'confirmed', Rules\Password::defaults()],
            'terms' => ['accepted'],
        ]);

        $plan = Plan::where('is_active', true)
            ->where('is_public', true)
            ->findOrFail($data['plan_id']);

        $amount = $data['billing_cycle'] === 'yearly'
            ? ($plan->effectivePriceYearly() ?: $plan->effectivePriceMonthly() * 12)
            : $plan->effectivePriceMonthly();

        $company = DB::transaction(function () use ($data, $plan, $amount) {
            $trialDays = (int) ($plan->trial_days ?: config('reservapro.trial_days', 14));
            $startsAt = now();
            $endsAt = $data['billing_cycle'] === 'yearly'
                ? now()->addYear()
                : now()->addMonth();

            $company = Company::create([
                'name' => $data['company_name'],
                'slug' => $this->uniqueCompanySlug($data['company_name']),
                'email' => $data['company_email'],
                'phone' => $data['company_phone'] ?? null,
                'whatsapp' => $data['company_phone'] ?? null,
                'address' => $data['company_address'] ?? null,
                'city' => $data['company_city'],
                'country' => $data['company_country'],
                'plan_id' => $plan->id,
                'status' => CompanyStatus::Trial,
                'trial_ends_at' => now()->addDays($trialDays),
                'subscription_starts_at' => $startsAt,
                'subscription_ends_at' => $endsAt,
                'timezone' => config('app.timezone', 'America/Bogota'),
                'locale' => 'es',
                'currency' => $plan->currency ?: config('reservapro.default_currency', 'COP'),
                'primary_color' => '#0f172a',
                'secondary_color' => '#22c7d9',
                'description' => 'Empresa creada desde el checkout de AsignaPro.',
            ]);

            $user = User::create([
                'company_id' => $company->id,
                'name' => trim($data['admin_first_name'].' '.$data['admin_last_name']),
                'email' => $data['admin_email'],
                'password' => Hash::make($data['password']),
                'phone' => $data['company_phone'] ?? null,
                'timezone' => config('app.timezone', 'America/Bogota'),
                'locale' => 'es',
                'is_active' => true,
            ]);

            Role::firstOrCreate(['name' => UserRole::CompanyAdmin->value, 'guard_name' => 'web']);
            $user->assignRole(UserRole::CompanyAdmin->value);

            $subscription = Subscription::create([
                'company_id' => $company->id,
                'plan_id' => $plan->id,
                'status' => SubscriptionStatus::Trial,
                'billing_cycle' => $data['billing_cycle'],
                'amount' => $amount,
                'currency' => $plan->currency ?: 'COP',
                'trial_starts_at' => now(),
                'trial_ends_at' => now()->addDays($trialDays),
                'current_period_start' => $startsAt,
                'current_period_end' => $endsAt,
                'metadata' => [
                    'source' => 'public_checkout',
                    'company_email' => $data['company_email'],
                ],
            ]);

            SubscriptionPayment::create([
                'subscription_id' => $subscription->id,
                'company_id' => $company->id,
                'reference' => 'SUB-'.now()->format('Ymd').'-'.Str::upper(Str::random(8)),
                'driver' => 'manual',
                'status' => 'pending',
                'amount' => $amount,
                'currency' => $plan->currency ?: 'COP',
                'period_start' => $startsAt,
                'period_end' => $endsAt,
                'notes' => 'Pago creado desde el checkout público.',
            ]);

            Auth::login($user);

            return $company;
        });

        return redirect()
            ->route('tenant.dashboard')
            ->with('success', 'Tu empresa fue creada. Completa el pago para activar tu suscripción.');
    }

    protected function uniqueCompanySlug(string $name): string
    {
        $base = Str::slug($name) ?: 'empresa';
        $slug = $base;
        $i = 2;

        while (Company::where('slug', $slug)->exists()) {
            $slug = $base.'-'.$i;
            $i++;
        }

        return $slug;
    }
}
