<?php

declare(strict_types=1);

namespace App\Livewire\Admin\Settings;

use App\Models\Setting;
use Illuminate\Support\Facades\Storage;
use Livewire\Attributes\Layout;
use Livewire\Attributes\Rule;
use Livewire\Component;
use Livewire\WithFileUploads;

#[Layout('layouts.admin')]
final class Edit extends Component
{
    use WithFileUploads;

    public Setting $setting;

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

    public $value = '';

    #[Rule('required|string|in:string,integer,boolean,file,text')]
    public string $type = 'string';

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

    #[Rule('nullable|string')]
    public ?string $description = null;

    public $file;

    public function mount(Setting $setting): void
    {
        $this->setting = $setting;
        $this->key = $setting->key;
        $this->value = $setting->value;
        $this->type = $setting->type;
        $this->group = $setting->group;
        $this->description = $setting->description;

        // Convert boolean values properly
        if ($this->type === 'boolean') {
            $this->value = (bool) $this->value;
        }
    }

    public function updateSetting(): void
    {
        // Custom validation based on type
        $rules = [
            'key' => 'required|string|max:255',
            'type' => 'required|string|in:string,integer,boolean,file,text',
            'group' => 'required|string|max:255',
            'description' => 'nullable|string',
        ];

        // Add value validation based on type
        switch ($this->type) {
            case 'boolean':
                $rules['value'] = 'required|boolean';
                break;
            case 'integer':
                $rules['value'] = 'required|integer';
                break;
            case 'file':
                $rules['file'] = 'nullable|file|image|max:2048';
                $rules['value'] = [
                    'required_without:file',
                    'string',
                    'max:2048',
                    function (string $attribute, mixed $val, \Closure $fail): void {
                        if ($this->file !== null) {
                            return;
                        }
                        $v = trim((string) $val);
                        if ($v === '') {
                            $fail(__('Enter an image URL or path, or upload a file.'));

                            return;
                        }
                        if (preg_match('#^https?://#i', $v)) {
                            return;
                        }
                        if (str_starts_with($v, '/')) {
                            return;
                        }
                        if (! str_contains($v, '..') && preg_match('#^[a-zA-Z0-9_\-/.]+$#', $v)) {
                            return;
                        }
                        $fail(__('Use a full URL (https://…), a path starting with /, or a storage path like settings/image.png.'));
                    },
                ];
                break;
            default:
                $rules['value'] = 'required|string';
                break;
        }

        $this->validate($rules);

        $value = $this->value;

        // Handle file upload for file type settings
        if ($this->type === 'file' && $this->file) {
            $previous = $this->setting->value;
            if ($previous && ! preg_match('#^https?://#i', $previous) && ! str_starts_with($previous, '/') && Storage::disk('public')->exists($previous)) {
                Storage::disk('public')->delete($previous);
            }

            $path = $this->file->store('settings', 'public');
            $value = $path;
        }

        // Convert boolean values to string for database storage
        $dbValue = $value;
        if ($this->type === 'boolean') {
            $dbValue = $this->value ? '1' : '0';
        }

        $this->setting->update([
            'key' => $this->key,
            'value' => $dbValue,
            'type' => $this->type,
            'group' => $this->group,
            'description' => $this->description,
        ]);

        activity()
            ->causedBy(auth()->user())
            ->performedOn($this->setting)
            ->withProperties([
                'setting_id' => $this->setting->id,
                'changes' => [
                    'key' => $this->key,
                    'value' => $value,
                    'type' => $this->type,
                    'group' => $this->group,
                    'description' => $this->description,
                ],
            ])
            ->log('setting_updated');

        session()->flash('success', 'Setting updated successfully!');
    }

    public function render()
    {
        return view('livewire.admin.settings.edit');
    }
}
