<?php

namespace App\Http\Livewire\SuperAdmin;

use App\Enums\CompanyStatus;
use App\Enums\UserRole;
use App\Models\Branch;
use App\Models\Company;
use App\Models\Plan;
use App\Models\User;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Str;
use Illuminate\Validation\Rule;
use Livewire\Attributes\Validate;
use Livewire\Component;
use Spatie\Permission\Models\Role;

class CompanyForm extends Component
{
    public ?Company $company = null;

    #[Validate('required|string|max:255')]
    public string $name = '';

    #[Validate('required|email|max:255')]
    public string $email = '';

    #[Validate('nullable|string|max:25')]
    public string $phone = '';

    #[Validate('nullable|string|max:25')]
    public string $whatsapp = '';

    #[Validate('nullable|string|max:50')]
    public string $document_number = '';

    #[Validate('nullable|string|max:100')]
    public string $city = '';

    #[Validate('nullable|string|max:255')]
    public string $address = '';

    #[Validate('required|exists:plans,id')]
    public ?int $plan_id = null;

    #[Validate('required|in:trial,active,suspended,cancelled')]
    public string $status = 'trial';

    public string $admin_name = '';

    public string $admin_email = '';

    public string $admin_phone = '';

    public string $admin_password = '';

    public string $admin_password_confirmation = '';

    public function mount(?string $uuid = null): void
    {
        if ($uuid) {
            $this->company = Company::where('uuid', $uuid)->firstOrFail();
            $data = $this->company->only([
                'name', 'email', 'phone', 'whatsapp', 'document_number',
                'city', 'address', 'plan_id',
            ]);

            foreach (['phone', 'whatsapp', 'document_number', 'city', 'address'] as $field) {
                $data[$field] = $data[$field] ?? '';
            }

            $this->fill($data);
            $this->status = $this->company->status->value;
        } else {
            $this->plan_id = Plan::active()->orderBy('sort_order')->value('id');
            $this->generatePassword();
        }
    }

    protected function rules(): array
    {
        $rules = [
            'name' => ['required', 'string', 'max:255'],
            'email' => ['required', 'email', 'max:255'],
            'phone' => ['nullable', 'string', 'max:25'],
            'whatsapp' => ['nullable', 'string', 'max:25'],
            'document_number' => ['nullable', 'string', 'max:50'],
            'city' => ['nullable', 'string', 'max:100'],
            'address' => ['nullable', 'string', 'max:255'],
            'plan_id' => ['required', 'exists:plans,id'],
            'status' => ['required', Rule::enum(CompanyStatus::class)],
        ];

        if (! $this->company) {
            $rules = array_merge($rules, [
                'admin_name' => ['required', 'string', 'max:255'],
                'admin_email' => ['required', 'email', 'max:255', Rule::unique('users', 'email')],
                'admin_phone' => ['nullable', 'string', 'max:25'],
                'admin_password' => ['required', 'string', 'min:8', 'confirmed'],
                'admin_password_confirmation' => ['required', 'string'],
            ]);
        }

        return $rules;
    }

    protected function validationAttributes(): array
    {
        return [
            'name' => 'nombre comercial',
            'email' => 'email de la empresa',
            'plan_id' => 'plan',
            'admin_name' => 'nombre del propietario',
            'admin_email' => 'email de acceso',
            'admin_phone' => 'celular del propietario',
            'admin_password' => 'contraseña inicial',
            'admin_password_confirmation' => 'confirmación de contraseña',
        ];
    }

    public function updatedEmail(string $value): void
    {
        if (! $this->company && $this->admin_email === '') {
            $this->admin_email = $value;
        }
    }

    public function generatePassword(): void
    {
        $password = Str::password(12, true, true, false, false);

        $this->admin_password = $password;
        $this->admin_password_confirmation = $password;
    }

    public function save()
    {
        $this->validate();

        $data = [
            'name'            => $this->name,
            'email'           => $this->email,
            'phone'           => $this->phone ?: null,
            'whatsapp'        => $this->whatsapp ?: null,
            'document_number' => $this->document_number ?: null,
            'city'            => $this->city ?: null,
            'address'         => $this->address ?: null,
            'plan_id'         => $this->plan_id,
            'status'          => $this->status,
        ];

        if ($this->company) {
            $this->company->update($data);
            session()->flash('success', 'Empresa actualizada correctamente.');
        } else {
            $company = DB::transaction(function () use ($data): Company {
                $data['slug'] = $this->makeUniqueSlug($this->name);
                $data['trial_ends_at'] = now()->addDays(config('reservapro.trial_days', 14));
                $company = Company::create($data);

                $branch = Branch::create([
                    'company_id' => $company->id,
                    'name'       => 'Sede Principal',
                    'slug'       => 'principal',
                    'phone'      => $company->phone,
                    'whatsapp'   => $company->whatsapp,
                    'email'      => $company->email,
                    'address'    => $company->address,
                    'city'       => $company->city,
                    'timezone'   => config('reservapro.default_timezone', 'America/Bogota'),
                    'is_main'    => true,
                    'is_active'  => true,
                ]);

                $admin = User::create([
                    'company_id' => $company->id,
                    'branch_id' => $branch->id,
                    'name' => $this->admin_name,
                    'email' => $this->admin_email,
                    'phone' => $this->admin_phone ?: null,
                    'password' => Hash::make($this->admin_password),
                    'timezone' => config('reservapro.default_timezone', 'America/Bogota'),
                    'locale' => config('reservapro.default_locale', 'es'),
                    'is_active' => true,
                    'email_verified_at' => now(),
                ]);

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

                $admin->assignRole(UserRole::CompanyAdmin->value);

                return $company;
            });

            session()->flash('success', "Empresa {$company->name} creada con acceso administrador para {$this->admin_email}.");
        }

        return redirect()->route('superadmin.companies.index');
    }

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

        do {
            $slug = $base.'-'.Str::random(4);
        } while (Company::where('slug', $slug)->exists());

        return $slug;
    }

    public function render()
    {
        return view('livewire.superadmin.company-form', [
            'plans' => Plan::active()->ordered()->get(),
            'admins' => $this->company
                ? $this->company->users()
                    ->whereHas('roles', fn ($query) => $query->where('name', UserRole::CompanyAdmin->value))
                    ->orderBy('name')
                    ->get()
                : collect(),
        ]);
    }
}
