<?php

namespace AleshaCMS\Http\Controllers\Frontend;

use AleshaCMS\Http\Controllers\Controller;
use AleshaCMS\Models\Post;
use AleshaCMS\Models\ViewLog;
use AleshaCMS\Models\CMS\Taxonomy;
use AleshaCMS\CMS\Theme\ThemeManager;
use AleshaCMS\CMS\Hook\HookManager;
use AleshaCMS\CMS\PageBuilder\PageBuilderRenderer;
use Illuminate\Http\Request;

class FrontendController extends Controller
{
    public function __construct(
        protected ThemeManager $theme,
        protected HookManager $hooks,
        protected PageBuilderRenderer $builder,
    ) {}

    public function resolve(Request $request, ?string $slug = null)
    {
        $slug = $slug ?: '/';

        // Homepage
        if ($slug === '/') {
            $homePageId = \AleshaCMS\Models\CMS\Setting::get('homepage_id');
            if ($homePageId) {
                $page = Post::find($homePageId);
                if ($page) {
                    return response($this->renderPost($page, 'page-home'));
                }
            }
            ViewLog::record(null, request());
            return response($this->renderThemeView('pages.home', []));
        }

        $segments = explode('/', trim($slug, '/'));

        // {type}/{post-slug} → single post
        if (count($segments) === 2) {
            [$typeSlug, $postSlug] = $segments;

            $builtinSlugs = ['post', 'page'];
            $contentTypeSlug = in_array($typeSlug, $builtinSlugs) ? $typeSlug : null;

            if (!$contentTypeSlug) {
                $ct = \AleshaCMS\Models\CMS\ContentType::where('rewrite_slug', $typeSlug)
                    ->orWhere('slug', $typeSlug)->first();
                $contentTypeSlug = $ct?->slug;
            }

            if ($contentTypeSlug) {
                $post = Post::where('slug', $postSlug)
                    ->where('content_type', $contentTypeSlug)
                    ->published()
                    ->with('taxonomies', 'author')
                    ->first();

                if ($post) {
                    return response($this->renderPost($post));
                }
            }
        }

        // Archive pages
        if (count($segments) >= 1) {
            $typeSlug = $segments[0];

            // Built-in types
            $builtins = [
                'post' => (object)['slug' => 'post', 'name' => 'Posts', 'has_archive' => true],
                'page' => (object)['slug' => 'page', 'name' => 'Pages', 'has_archive' => true],
            ];

            $contentType = $builtins[$typeSlug]
                ?? \AleshaCMS\Models\CMS\ContentType::where('rewrite_slug', $typeSlug)
                    ->orWhere('slug', $typeSlug)
                    ->where('has_archive', true)
                    ->first();

            if ($contentType) {
                $query = Post::ofType($contentType->slug)
                    ->published()
                    ->with('taxonomies', 'author')
                    ->latest('published_at');

                // Filter by category if provided
                if ($request->category) {
                    $query->whereHas('taxonomies', fn($q) =>
                        $q->where('type', 'category')->where('slug', $request->category)
                    );
                }

                // Filter by search keyword
                if ($request->search) {
                    $term = $request->search;
                    $query->where(fn($q) =>
                        $q->where('title', 'like', "%{$term}%")
                          ->orWhere('excerpt', 'like', "%{$term}%")
                          ->orWhere('content', 'like', "%{$term}%")
                    );
                }

                $posts = $query->paginate(12);

                $categories = Taxonomy::where('type', 'category')
                    ->withCount(['posts' => fn($q) => $q->ofType($contentType->slug)->published()])
                    ->having('posts_count', '>', 0)
                    ->orderBy('name')
                    ->get();

                $search = $request->search;
                ViewLog::record(null, request());
                return response($this->renderThemeView('pages.archive', compact('posts', 'contentType', 'categories', 'search')));
            }
        }

        abort(404);
    }

    public function taxonomyArchive(Request $request, string $slug)
    {
        $taxonomy = Taxonomy::where('slug', $slug)->firstOrFail();

        $posts = Post::published()
            ->with('taxonomies', 'author')
            ->whereHas('taxonomies', fn($q) => $q->where('taxonomies.id', $taxonomy->id))
            ->latest('published_at')
            ->paginate(12);

        $contentType = (object)['slug' => 'post', 'name' => $taxonomy->name, 'has_archive' => true];

        $categories = Taxonomy::where('type', 'category')
            ->withCount(['posts' => fn($q) => $q->published()])
            ->having('posts_count', '>', 0)
            ->orderBy('name')
            ->get();

        ViewLog::record(null, request());
        return response($this->renderThemeView('pages.taxonomy', compact('posts', 'taxonomy', 'contentType', 'categories')));
    }

    protected function renderPost(Post $post, string $templateHint = null): string
    {
        ViewLog::record($post, request());
        $this->hooks->fire('post.before_render', ['post' => $post]);

        // Ensure taxonomies are loaded
        if (!$post->relationLoaded('taxonomies')) {
            $post->load('taxonomies');
        }

        $template = $templateHint ?? "single-{$post->content_type}";
        $pageBuilderHtml = null;

        if ($post->page_builder) {
            $pageBuilderHtml = $this->builder->render($post->page_builder);
        }

        $builderFullpage = (bool)$post->builder_fullpage;

        $data = compact('post', 'pageBuilderHtml', 'builderFullpage');
        $data = $this->hooks->applyFilter('post.render_data', $data, ['post' => $post]);

        return $this->renderThemeView($template, $data);
    }

    protected function renderThemeView(string $template, array $data): string
    {
        $view = $this->theme->resolveView($template);

        if (!view()->exists($view)) {
            $fallbacks = ['pages.single', 'pages.default', 'index'];
            foreach ($fallbacks as $fallback) {
                $fallbackView = $this->theme->resolveView($fallback);
                if (view()->exists($fallbackView)) {
                    return view($fallbackView, $data)->render();
                }
            }
            abort(404);
        }

        return view($view, $data)->render();
    }
}
