<?php

namespace Daylight\Core\Http\Controllers\Content;

use Daylight\Core\Http\Controllers\Controller;
use Daylight\Core\Http\Requests\Content\Pages\StorePageRequest;
use Daylight\Core\Http\Requests\Content\Pages\UpdatePageRequest;
use Daylight\Core\Models\Page;
use Daylight\Core\Modules\PageBuilder\Registries\ComponentRegistry;
use Daylight\Core\Modules\PageBuilder\Registries\TemplateRegistry;
use Daylight\Core\Settings\General;
use Illuminate\Http\RedirectResponse;
use Illuminate\Routing\Controllers\HasMiddleware;
use Illuminate\Routing\Controllers\Middleware;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\DB;
use Illuminate\View\View;
use Spatie\ResponseCache\Facades\ResponseCache;

class PageController extends Controller implements HasMiddleware
{
    public static function middleware(): array
    {
        return [
            new Middleware('can:create:pages', only: ['create', 'store', 'duplicate']),
            new Middleware('can:read:pages', only: ['index', 'show']),
            new Middleware('can:update:pages', only: ['edit', 'update']),
            new Middleware('can:delete:pages', only: ['destroy']),
        ];
    }

    public function index(): View
    {
        return view('daylight::content.pages.index');
    }

    public function create(): View
    {
        return view('daylight::content.pages.create', [
            'availableComponents' => $this->getAvailableComponents(),
            'templates' => app(TemplateRegistry::class)->all(),
            'pages' => $this->getPagesList(),
        ]);
    }

    public function store(StorePageRequest $request)
    {
        $page = tap((daylightModel('page'))::create([
            'template' => $request->get('template', 'default'),
            'parent_id' => $request->get('parent_id') ?: null,
        ]), function (Page $page) use ($request) {
            $translation = $page->translations()->create(
                attributes: $request->safe(['locale', 'name', 'slug', 'meta_title', 'meta_description', 'robots'])
            );

            $translation->components()->createMany($request->getComponentsFromRequest());
        });

        return redirect()
            ->route('daylight.content.pages.edit', [
                'page' => $page,
                'locale' => $request->get('locale', app()->getLocale()),
            ])
            ->with('success', __('daylight::content.page_created'));
    }

    public function edit(Page $page)
    {
        $page->load([
            'translations' => function ($query) {
                $query
                    ->with('components.relatables', 'components.media')
                    ->where('locale', request()->get('locale', app()->getLocale()));
            },
        ]);

        return view('daylight::content.pages.edit', [
            'page' => $page,
            'components' => $page->translations->first()->formattedComponentData,
            'availableComponents' => $this->getAvailableComponents(),
            'templates' => app(TemplateRegistry::class)->all(),
            'pages' => $this->getPagesList($page->id),
        ]);
    }

    public function update(UpdatePageRequest $request, Page $page)
    {
        $page->update([
            'template' => $request->get('template', 'default'),
            'parent_id' => $request->get('parent_id') ?: null,
        ]);

        $translation = $page->translations()->updateOrCreate(
            ['locale' => $request->get('locale')],
            $request->safe(['name', 'slug', 'meta_title', 'meta_description', 'robots'])
        );

        if (app(General::class)->frontPage === $page->id) {
            ResponseCache::forget('/');
        } else {
            ResponseCache::forget(str_ireplace(config('app.url'), '', translatedRoute('page', $translation['slug'])));
        }

        app(\Daylight\Core\Modules\PageBuilder\Services\ComponentSyncService::class)->sync(
            $request->getComponentsFromRequest(),
            $translation
        );

        return redirect()
            ->route('daylight.content.pages.edit', [
                'page' => $page,
                'locale' => $request->get('locale', app()->getLocale()),
            ])
            ->with('success', __('daylight::content.page_updated'));
    }

    public function duplicate(Page $page): RedirectResponse
    {
        $page->load('translations.components.media', 'translations.components.relatables');

        $newPage = DB::transaction(function () use ($page) {
            $newPage = $page->replicate(['id']);
            $newPage->save();

            foreach ($page->translations as $translation) {
                $newTranslation = $translation->replicate(['id', 'page_id']);
                $newTranslation->page_id = $newPage->id;
                $newTranslation->name = __('daylight::content.copy_of', ['name' => $translation->name]);
                $newTranslation->slug = $translation->slug . '-kopie';
                $newTranslation->save();

                foreach ($translation->components as $component) {
                    $newComponent = $component->replicate(['id', 'buildable_id', 'buildable_type']);
                    $newComponent->buildable_id = $newTranslation->id;
                    $newComponent->buildable_type = $newTranslation->getMorphClass();
                    $newComponent->save();

                    // Copy media pivot entries
                    foreach ($component->media as $media) {
                        $newComponent->media()->attach($media->id, [
                            'properties' => $media->pivot->properties,
                            'order' => $media->pivot->order,
                        ]);
                    }

                    // Copy relatable pivot entries
                    foreach ($component->relatables as $relatable) {
                        $newComponent->relatables()->create([
                            'relatable_type' => $relatable->relatable_type,
                            'relatable_id' => $relatable->relatable_id,
                            'order' => $relatable->order,
                        ]);
                    }
                }
            }

            return $newPage;
        });

        return redirect()
            ->route('daylight.content.pages.edit', ['page' => $newPage])
            ->with('success', __('daylight::content.page_duplicated'));
    }

    public function destroy(Page $page): RedirectResponse
    {
        $page->delete();

        return redirect()->route('daylight.content.pages.index')
            ->with('success', __('daylight::content.page_deleted'));
    }

    private function getAvailableComponents(): Collection
    {
        return app(ComponentRegistry::class)
            ->availableFor(daylightModel('page'))
            ->map(fn ($component) => $component->toArray())
            ->values();
    }

    private function getPagesList(?int $excludeId = null): Collection
    {
        $query = (daylightModel('page'))::query()
            ->with(['defaultTranslation', 'translations']);

        if ($excludeId) {
            // Exclude the page itself and its descendants
            $page = (daylightModel('page'))::find($excludeId);
            $descendantIds = $page?->descendantsAndSelf()->pluck('id')->toArray() ?? [];
            $query->whereNotIn('id', $descendantIds);
        }

        return $query->get();
    }
}
