<?php

namespace FluxCms\Core\Models;

use FluxCms\Core\Services\ComponentRegistry;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Spatie\MediaLibrary\HasMedia;
use Spatie\MediaLibrary\InteractsWithMedia;
use Spatie\MediaLibrary\MediaCollections\Models\Media;
use Spatie\Translatable\HasTranslations;

class PageComponent extends Model implements HasMedia
{
    use HasTranslations, InteractsWithMedia;

    public function getTable()
    {
        return config('flux-cms.database.table_prefix', 'flux_cms_').'page_components';
    }

    protected $fillable = [
        'page_id',
        'component_class',
        'order',
        'content',
        'is_active',
        'settings',
    ];

    protected $translatable = [
        'content',
    ];

    protected $casts = [
        'content' => 'array',
        'settings' => 'array',
        'is_active' => 'boolean',
    ];

    public function page(): BelongsTo
    {
        return $this->belongsTo(Page::class, 'page_id');
    }

    /**
     * Media Collections für Component Assets
     */
    public function registerMediaCollections(): void
    {
        $this->addMediaCollection('component_images')
            ->acceptsMimeTypes(['image/jpeg', 'image/png', 'image/webp', 'image/svg+xml']);

        $this->addMediaCollection('component_files')
            ->acceptsMimeTypes([
                'application/pdf',
                'application/msword',
                'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
                'text/plain',
            ]);

        $this->addMediaCollection('component_videos')
            ->acceptsMimeTypes(['video/mp4', 'video/webm', 'video/ogg']);
    }

    public function registerMediaConversions(?Media $media = null): void
    {
        $this->addMediaConversion('thumb')
            ->width(300)
            ->height(300)
            ->sharpen(10);

        $this->addMediaConversion('medium')
            ->width(800)
            ->height(600)
            ->sharpen(10);

        $this->addMediaConversion('large')
            ->width(1200)
            ->height(900)
            ->sharpen(10);
    }

    /**
     * Component Configuration
     */
    public function getComponentConfig(): array
    {
        if (! class_exists($this->component_class)) {
            return [
                'name' => 'Unknown Component',
                'fields' => [],
                'category' => 'Unknown',
                'error' => 'Component class not found: '.$this->component_class,
            ];
        }

        $registry = app(ComponentRegistry::class);

        return $registry->getComponentConfig($this->component_class);
    }

    /**
     * Content Validation
     */
    public function validateContent(): array
    {
        if (! class_exists($this->component_class)) {
            return ['component_class' => 'Component class not found'];
        }

        $registry = app(ComponentRegistry::class);

        return $registry->validateComponentContent($this->component_class, $this->content ?? []);
    }

    /**
     * Scopes
     */
    public function scopeActive($query)
    {
        return $query->where('is_active', true);
    }

    public function scopeOrdered($query)
    {
        return $query->orderBy('order');
    }

    public function scopeByComponentClass($query, string $componentClass)
    {
        return $query->where('component_class', $componentClass);
    }

    /**
     * Content Management
     */
    public function getTranslatedContent(?string $locale = null): array
    {
        $locale = $locale ?? app()->getLocale();
        $content = $this->getTranslations('content');

        return $content[$locale] ?? $content[config('app.fallback_locale')] ?? [];
    }

    public function setTranslatedContent(array $content, ?string $locale = null): void
    {
        $locale = $locale ?? app()->getLocale();
        $translations = $this->getTranslations('content');
        $translations[$locale] = $content;
        $this->content = $translations;
        $this->save();
    }

    public function getContentValue(string $key, ?string $locale = null): mixed
    {
        $content = $this->getTranslatedContent($locale);

        return data_get($content, $key);
    }

    public function setContentValue(string $key, mixed $value, ?string $locale = null): void
    {
        $content = $this->getTranslatedContent($locale);
        data_set($content, $key, $value);
        $this->setTranslatedContent($content, $locale);
    }

    /**
     * Component Rendering
     */
    public function canRender(): bool
    {
        return class_exists($this->component_class) && $this->is_active;
    }

    public function getComponentName(): string
    {
        $config = $this->getComponentConfig();

        return $config['name'] ?? class_basename($this->component_class);
    }

    public function getComponentCategory(): string
    {
        $config = $this->getComponentConfig();

        return $config['category'] ?? 'General';
    }

    /**
     * Duplication
     */
    public function duplicate(?int $newOrder = null): self
    {
        $duplicate = $this->replicate();
        $duplicate->order = $newOrder ?? ($this->page->allComponents()->max('order') + 1);
        $duplicate->save();

        // Copy media if any
        foreach ($this->getMedia() as $media) {
            $media->copy($duplicate);
        }

        return $duplicate;
    }

    /**
     * Settings Management
     */
    public function getSetting(string $key, mixed $default = null): mixed
    {
        return data_get($this->settings, $key, $default);
    }

    public function setSetting(string $key, mixed $value): void
    {
        $settings = $this->settings ?? [];
        data_set($settings, $key, $value);
        $this->update(['settings' => $settings]);
    }
}
