<?php

namespace FleekDash\Core;

use FleekDash\Traits\Base;
use WP_Post;
use WP_Query;

/**
 * Class Template
 *
 * Represents the Template class for FleekDash.
 *
 * @package FleekDash\Core
 */
class Template
{
    use Base;

    public const FRONTEND_TEMPLATE = 'frontend-template.php';
    public const FRONTEND_TEMPLATE_NAME = 'FleekDash';
    public const FRONTEND_TEMPLATE_SLUG = 'fleekdash';

    /**
     * Initialize the class.
     */
    public function init(): void
    {
        \add_filter('theme_page_templates', [$this, 'customTemplate']);
        // Use high priority to ensure our template loads before other filters
        \add_filter('template_include', [$this, 'loadCustomTemplate'], 99);
        // Also hook into template_redirect to ensure page is found
        \add_action('template_redirect', [$this, 'ensurePageTemplate'], 1);
    }

    /**
     * Add custom template to theme.
     *
     * @param array<string, string> $templates List of templates.
     *
     * @return array<string, string>
     */
    public function customTemplate(array $templates): array
    {
        $templates[self::FRONTEND_TEMPLATE] = self::FRONTEND_TEMPLATE_NAME;

        return $templates;
    }

    /**
     * Load custom template.
     *
     * @param string $template Template file.
     */
    public function loadCustomTemplate(string $template): string
    {
        $resolved = $template;
        if (!\is_page()) {
            return $resolved;
        }

        $pageTemplateSlug = \get_page_template_slug();
        if ($pageTemplateSlug === '') {
            return $resolved;
        }

        $pluginPath = $this->resolvePluginTemplatePath($pageTemplateSlug);

        return $pluginPath ?? $resolved;
    }

    /**
     * Resolve path to a plugin page template file, or null if not found.
     */
    private function resolvePluginTemplatePath(string $pageTemplateSlug): ?string
    {
        $pluginTemplateDirs = [
            \FLEEKDASH_DIR . 'views/',
            \FLEEKDASH_DIR . 'views/templates/',
        ];

        $result = null;
        if ($pageTemplateSlug === self::FRONTEND_TEMPLATE) {
            $frontendPath = \FLEEKDASH_DIR . 'views/templates/' . self::FRONTEND_TEMPLATE;
            $result = \file_exists($frontendPath) ? $frontendPath : null;
        } else {
            $result = $this->findExistingTemplateFile($pluginTemplateDirs, $pageTemplateSlug);
            if ($result === null) {
                $filename = \basename($pageTemplateSlug);
                if ($filename !== $pageTemplateSlug) {
                    $result = $this->findExistingTemplateFile($pluginTemplateDirs, $filename);
                }
            }
        }

        return $result;
    }

    /**
     * @param array<int, string> $dirs
     */
    private function findExistingTemplateFile(array $dirs, string $relativeName): ?string
    {
        foreach ($dirs as $dir) {
            $templateFilePath = $dir . $relativeName;
            if (\file_exists($templateFilePath)) {
                return $templateFilePath;
            }
        }

        return null;
    }

    /**
     * Ensure page with custom template is found (prevent 404).
     */
    public function ensurePageTemplate(): void
    {
        global $wp_query;

        if (!\is_404()) {
            return;
        }

        $pagename = $this->resolvePagenameFromRequest($wp_query);
        if ($pagename === '') {
            return;
        }

        $page = $this->findPublishedPageByPagename($pagename);
        if (
            $page === null
            || $page->post_status !== 'publish'
            || !$this->shouldRepairQueryForPage($page)
        ) {
            return;
        }

        $this->repairMainQueryForPage($wp_query, $page);
    }

    private function resolvePagenameFromRequest(WP_Query $wpQuery): string
    {
        $pagename = $wpQuery->query_vars['pagename'] ?? '';
        if ($pagename !== '') {
            return $pagename;
        }

        $requestUri = $_SERVER['REQUEST_URI'] ?? '';
        $path = \trim((string) \parse_url($requestUri, PHP_URL_PATH), '/');

        $homePath = \parse_url(\home_url(), PHP_URL_PATH);
        if ($homePath) {
            $homePathTrimmed = \trim($homePath, '/');
            if ($homePathTrimmed !== '') {
                $path = \str_replace($homePathTrimmed . '/', '', $path);
                $path = \str_replace('/' . $homePathTrimmed, '', $path);
                $path = \trim($path, '/');
            }
        }

        $path = \strtok($path, '?');

        return $path !== false ? $path : '';
    }

    private function findPublishedPageByPagename(string $pagename): ?WP_Post
    {
        $page = \get_page_by_path($pagename);
        $parts = \explode('/', $pagename);
        $slug = \end($parts);

        if (!$page instanceof WP_Post) {
            $page = \get_page_by_path($slug);
        }
        if (!$page instanceof WP_Post) {
            $pages = \get_posts([
                'post_type' => 'page',
                'post_status' => 'publish',
                'name' => $slug,
                'numberposts' => 1,
                'posts_per_page' => 1,
            ]);
            $page = (!empty($pages[0]) && $pages[0] instanceof WP_Post) ? $pages[0] : null;
        }
        if (!$page instanceof WP_Post && \strpos($pagename, '/') !== false) {
            $page = \get_page_by_path($pagename);
        }

        return $page instanceof WP_Post ? $page : null;
    }

    private function shouldRepairQueryForPage(WP_Post $page): bool
    {
        $loginPageId = (int) \get_option('fleekdash_login_page_id', 0);
        if ($loginPageId > 0 && (int) $page->ID === $loginPageId) {
            return true;
        }

        $template = \get_post_meta($page->ID, '_wp_page_template', true);
        if ($template === '' || $template === false) {
            return false;
        }

        return $template === self::FRONTEND_TEMPLATE
            || \strpos((string) $template, 'login-template.php') !== false
            || \strpos((string) $template, 'frontend-template.php') !== false;
    }

    private function repairMainQueryForPage(WP_Query $wpQuery, WP_Post $page): void
    {
        $wpQuery->is_404 = false;
        $wpQuery->is_page = true;
        $wpQuery->is_singular = true;
        $wpQuery->queried_object = $page;
        $wpQuery->queried_object_id = $page->ID;
        $wpQuery->posts = [$page];
        $wpQuery->post_count = 1;
        $wpQuery->found_posts = 1;
        $wpQuery->post = $page;

        $wpQuery->query_vars['page_id'] = $page->ID;
        $wpQuery->query_vars['pagename'] = $page->post_name;

        /*
         * WP::handle_404() runs before template_redirect and already called status_header(404).
         * We fixed the main query here, but the response code stays 404 unless reset — that
         * shows in DevTools as "GET /adm/ 404" even when the login template renders.
         */
        if (!\headers_sent()) {
            \status_header(200);
        }
    }
}
