<?php

namespace FluxCms\Core\Models;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;

class PageVersion extends Model
{
    public function getTable()
    {
        return config('flux-cms.database.table_prefix', 'flux_cms_').'page_versions';
    }

    protected $fillable = [
        'page_id',
        'page_data',
        'components_data',
        'version_name',
        'change_description',
        'created_by_type',
        'created_by_id',
    ];

    protected $casts = [
        'page_data' => 'array',
        'components_data' => 'array',
    ];

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

    public function createdBy()
    {
        return $this->morphTo('created_by');
    }

    /**
     * Restore this version
     */
    public function restore(): void
    {
        $page = $this->page;

        // Create backup of current version
        $page->createVersion('Backup before restoration');

        // Restore page data
        $pageData = $this->page_data;
        unset($pageData['id'], $pageData['created_at'], $pageData['updated_at']);
        $page->update($pageData);

        // Delete current components and restore from version
        $page->allComponents()->delete();

        foreach ($this->components_data as $componentData) {
            unset($componentData['id'], $componentData['page_id'], $componentData['created_at'], $componentData['updated_at']);
            $page->allComponents()->create($componentData);
        }
    }

    /**
     * Get differences compared to current version
     */
    public function getDifferences(): array
    {
        $currentPage = $this->page->fresh();
        $currentComponents = $currentPage->allComponents()->get();

        return [
            'page_changes' => $this->arrayDiff($this->page_data, $currentPage->toArray()),
            'components_changes' => $this->arrayDiff($this->components_data, $currentComponents->toArray()),
        ];
    }

    private function arrayDiff(array $old, array $new): array
    {
        $changes = [];

        foreach ($old as $key => $value) {
            if (! isset($new[$key])) {
                $changes['removed'][$key] = $value;
            } elseif ($new[$key] !== $value) {
                $changes['changed'][$key] = [
                    'old' => $value,
                    'new' => $new[$key],
                ];
            }
        }

        foreach ($new as $key => $value) {
            if (! isset($old[$key])) {
                $changes['added'][$key] = $value;
            }
        }

        return $changes;
    }
}
