<?php

namespace App\Livewire\Settings;

use App\Models\User;
use DateTimeZone;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Session;
use Illuminate\Validation\Rule;
use Livewire\Component;
use Livewire\Features\SupportFileUploads\TemporaryUploadedFile;
use Livewire\WithFileUploads;

class Profile extends Component
{
    use WithFileUploads;

    public string $first_name = '';

    public string $last_name = '';

    public string $email = '';

    public ?string $phone = null;

    public ?string $address_street = null;

    public ?string $address_city = null;

    public ?string $address_postal = null;

    public string $timezone = '';

    public ?TemporaryUploadedFile $profilePicture = null;

    public bool $removeProfilePicture = false;

    /**
     * Mount the component.
     */
    public function mount(): void
    {
        $user = Auth::user();
        $this->first_name = $user->first_name ?? '';
        $this->last_name = $user->last_name ?? '';
        $this->email = $user->email;
        $this->phone = $user->phone ?? '';
        $this->address_street = $user->address_street ?? '';
        $this->address_city = $user->address_city ?? '';
        $this->address_postal = $user->address_postal ?? '';
        $this->timezone = $user->timezone ?? config('app.timezone');
    }

    /**
     * Update the profile information for the currently authenticated user.
     */
    public function updateProfileInformation(): void
    {
        $user = Auth::user();

        if ($user->isDemoUser()) {
            $this->addError('demo_restriction', 'Demo user profile cannot be modified.');

            return;
        }

        $validated = $this->validate([
            ...User::nameValidationRules(),
            'email' => [
                'required',
                'string',
                'lowercase',
                'email',
                'max:255',
                Rule::unique(User::class)->ignore($user->id),
            ],
            'phone' => ['nullable', 'string', 'max:20'],
            'address_street' => ['nullable', 'string', 'max:255'],
            'address_city' => ['nullable', 'string', 'max:255'],
            'address_postal' => ['nullable', 'string', 'max:20'],
            'timezone' => ['required', 'string', 'timezone'],
            'profilePicture' => ['nullable', 'image', 'mimes:jpeg,jpg,png,webp', 'max:12288'],
        ]);

        $user->fill([
            'first_name' => $validated['first_name'],
            'last_name' => $validated['last_name'],
            'email' => $validated['email'],
            'phone' => $validated['phone'],
            'address_street' => $validated['address_street'],
            'address_city' => $validated['address_city'],
            'address_postal' => $validated['address_postal'],
            'timezone' => $validated['timezone'],
        ]);

        if ($user->isDirty('email')) {
            $user->email_verified_at = null;
        }

        if ($this->removeProfilePicture && $user->profile_picture) {
            $user->profile_picture = null;
        }

        if ($this->profilePicture) {
            $filename = 'profile-pictures/'.uniqid().'.'.$this->profilePicture->getClientOriginalExtension();
            $this->profilePicture->storeAs('', $filename, 'public');
            $user->profile_picture = $filename;
        }

        $user->save();

        $this->reset(['profilePicture', 'removeProfilePicture']);

        $this->dispatch('profile-updated', name: $user->name);
    }

    /**
     * Send an email verification notification to the current user.
     */
    public function resendVerificationNotification(): void
    {
        $user = Auth::user();

        if ($user->hasVerifiedEmail()) {
            $this->redirectIntended(default: route('dashboard', absolute: false));

            return;
        }

        $user->sendEmailVerificationNotification();

        Session::flash('status', 'verification-link-sent');
    }

    /**
     * Get the list of available timezones.
     *
     * @return array<string, string>
     */
    public function getTimezoneOptions(): array
    {
        return collect(DateTimeZone::listIdentifiers())
            ->mapWithKeys(fn ($tz) => [$tz => $tz])
            ->toArray();
    }

    public function render(): mixed
    {
        return view('livewire.settings.profile');
    }
}
