<?php

namespace App\Http\Controllers;

use App\Core\Controller;
use App\Core\Request;
use App\Core\Response;
use App\Models\Menu;

/**
 * ITSWEBER CMS – Frontend Search Controller
 *
 * Searches across pages, blog posts, events, and downloads.
 * Respects the search_enabled setting (toggleable in Admin → Settings).
 */
class SearchController extends Controller
{
    private const RESULTS_PER_PAGE = 20;
    private const MIN_QUERY_LENGTH = 2;
    private const MAX_QUERY_LENGTH = 200;
    private const EXCERPT_LENGTH = 200;

    public function index(Request $request, array $params = []): void
    {
        // Check if search is enabled
        if (setting('search_enabled', '1') !== '1') {
            http_response_code(404);
            $this->renderFrontend('404', ['current_uri' => '/search']);
            return;
        }

        $query = trim($request->query('q') ?? '');
        $query = mb_substr($query, 0, self::MAX_QUERY_LENGTH);

        // No query – show empty search page
        if ($query === '') {
            $this->renderFrontend('search', [
                'page_title'      => __('theme.search_title'),
                'seo_title'       => __('theme.search_title') . ' – ' . setting('site_name'),
                'query'           => '',
                'results'         => [],
                'total_results'   => 0,
                'pagination'      => null,
                'breadcrumbs'     => [
                    ['label' => 'Home', 'url' => '/'],
                    ['label' => __('theme.search_title'), 'url' => null],
                ],
                'current_uri'     => '/search',
            ]);
            return;
        }

        // Query too short
        if (mb_strlen($query) < self::MIN_QUERY_LENGTH) {
            $this->renderFrontend('search', [
                'page_title'      => __('theme.search_title'),
                'seo_title'       => __('theme.search_title') . ' – ' . setting('site_name'),
                'query'           => $query,
                'results'         => [],
                'total_results'   => 0,
                'error_message'   => __('theme.search_min_length', ['min' => self::MIN_QUERY_LENGTH]),
                'pagination'      => null,
                'breadcrumbs'     => [
                    ['label' => 'Home', 'url' => '/'],
                    ['label' => __('theme.search_title'), 'url' => null],
                ],
                'current_uri'     => '/search',
            ]);
            return;
        }

        // Perform search
        $currentPage = max(1, (int) ($request->query('page') ?? 1));
        $allResults  = $this->searchAll($query);
        $total       = count($allResults);
        $totalPages  = max(1, (int) ceil($total / self::RESULTS_PER_PAGE));
        $currentPage = min($currentPage, $totalPages);
        $offset      = ($currentPage - 1) * self::RESULTS_PER_PAGE;
        $results     = array_slice($allResults, $offset, self::RESULTS_PER_PAGE);

        $this->renderFrontend('search', [
            'page_title'      => __('theme.search_results_for', ['query' => $query]),
            'seo_title'       => __('theme.search_results_for', ['query' => $query]) . ' – ' . setting('site_name'),
            'query'           => $query,
            'results'         => $results,
            'total_results'   => $total,
            'pagination'      => $total > self::RESULTS_PER_PAGE ? [
                'current_page' => $currentPage,
                'total_pages'  => $totalPages,
                'total_posts'  => $total,
                'base_url'     => '/search?q=' . urlencode($query),
            ] : null,
            'breadcrumbs'     => [
                ['label' => 'Home', 'url' => '/'],
                ['label' => __('theme.search_title'), 'url' => null],
            ],
            'current_uri'     => '/search',
        ]);
    }

    /**
     * Search across all content types and return merged, relevance-sorted results.
     */
    private function searchAll(string $query): array
    {
        $results = [];
        $like    = '%' . $query . '%';

        // 1. Pages (published, non-homepage)
        $pages = $this->db()->fetchAll(
            "SELECT id, title, slug, content, seo_description, 'page' AS result_type
             FROM iw_pages
             WHERE status = 'published'
               AND is_homepage = 0
               AND (title LIKE :q1 OR content LIKE :q2 OR seo_description LIKE :q3)
             ORDER BY title ASC",
            ['q1' => $like, 'q2' => $like, 'q3' => $like]
        );
        foreach ($pages as $page) {
            $results[] = [
                'type'    => 'page',
                'title'   => $page['title'],
                'url'     => '/' . $page['slug'],
                'excerpt' => $this->buildExcerpt($page['content'], $query, $page['seo_description']),
                'date'    => null,
                'icon'    => 'file-text',
            ];
        }

        // 2. Blog posts (published)
        $posts = $this->db()->fetchAll(
            "SELECT p.id, p.title, p.slug, p.content, p.excerpt AS post_excerpt,
                    p.published_at, p.featured_image, u.username AS author_name,
                    'blog' AS result_type
             FROM iw_blog_posts p
             LEFT JOIN iw_users u ON p.author_id = u.id
             WHERE p.status = 'published'
               AND (p.title LIKE :q1 OR p.content LIKE :q2 OR p.excerpt LIKE :q3)
             ORDER BY p.published_at DESC",
            ['q1' => $like, 'q2' => $like, 'q3' => $like]
        );
        foreach ($posts as $post) {
            $results[] = [
                'type'    => 'blog',
                'title'   => $post['title'],
                'url'     => '/blog/' . $post['slug'],
                'excerpt' => $this->buildExcerpt($post['content'], $query, $post['post_excerpt']),
                'date'    => $post['published_at'],
                'image'   => $post['featured_image'] ?? null,
                'author'  => $post['author_name'] ?? null,
                'icon'    => 'book-open',
            ];
        }

        // 3. Events (published) – table may not exist
        try {
            $events = $this->db()->fetchAll(
                "SELECT id, title, slug, COALESCE(excerpt, content) AS content, start_date AS event_date,
                        'event' AS result_type
                 FROM iw_events
                 WHERE publish_status = 'published'
                   AND (title LIKE :q1 OR excerpt LIKE :q2 OR content LIKE :q3)
                 ORDER BY start_date DESC",
                ['q1' => $like, 'q2' => $like, 'q3' => $like]
            );
            foreach ($events as $event) {
                $results[] = [
                    'type'    => 'event',
                    'title'   => $event['title'],
                    'url'     => '/events/' . $event['slug'],
                    'excerpt' => $this->buildExcerpt($event['content'], $query),
                    'date'    => $event['event_date'],
                    'icon'    => 'calendar',
                ];
            }
        } catch (\PDOException $e) {
            // Table does not exist – skip silently
        }

        // 4. Downloads (published) – table may not exist
        try {
            $downloads = $this->db()->fetchAll(
                "SELECT id, title, slug, COALESCE(excerpt, content) AS content,
                        'download' AS result_type
                 FROM iw_downloads
                 WHERE status = 'published'
                   AND (title LIKE :q1 OR excerpt LIKE :q2 OR content LIKE :q3)
                 ORDER BY title ASC",
                ['q1' => $like, 'q2' => $like, 'q3' => $like]
            );
            foreach ($downloads as $dl) {
                $results[] = [
                    'type'    => 'download',
                    'title'   => $dl['title'],
                    'url'     => '/download/' . $dl['slug'],
                    'excerpt' => $this->buildExcerpt($dl['content'], $query),
                    'date'    => null,
                    'icon'    => 'download',
                ];
            }
        } catch (\PDOException $e) {
            // Table does not exist – skip silently
        }

        // Sort: title matches first, then by date (newest first)
        usort($results, function ($a, $b) use ($query) {
            $aTitle = stripos($a['title'], $query) !== false ? 0 : 1;
            $bTitle = stripos($b['title'], $query) !== false ? 0 : 1;
            if ($aTitle !== $bTitle) {
                return $aTitle - $bTitle;
            }
            // Secondary: by date (newest first), nulls last
            $aDate = $a['date'] ?? '0000-00-00';
            $bDate = $b['date'] ?? '0000-00-00';
            return strcmp($bDate, $aDate);
        });

        return $results;
    }

    /**
     * Build an excerpt from content, trying to show the matched area.
     */
    private function buildExcerpt(string $content, string $query, ?string $fallbackExcerpt = null): string
    {
        // Remove <style> and <script> blocks (including content) before stripping tags
        $text = preg_replace('/<style\b[^>]*>.*?<\/style>/is', '', $content);
        $text = preg_replace('/<script\b[^>]*>.*?<\/script>/is', '', $text);
        $text = strip_tags($text);
        $text = trim(preg_replace('/\s+/', ' ', $text));

        if ($text === '' && $fallbackExcerpt) {
            return str_truncate(strip_tags($fallbackExcerpt), self::EXCERPT_LENGTH);
        }

        if ($text === '') {
            return '';
        }

        // Try to find the query in text and show context around it
        $pos = mb_stripos($text, $query);
        if ($pos !== false) {
            $start = max(0, $pos - 80);
            $excerpt = mb_substr($text, $start, self::EXCERPT_LENGTH);
            if ($start > 0) {
                $excerpt = '...' . $excerpt;
            }
            if (mb_strlen($text) > $start + self::EXCERPT_LENGTH) {
                $excerpt .= '...';
            }
            return $excerpt;
        }

        // Fallback: beginning of text
        return str_truncate($text, self::EXCERPT_LENGTH);
    }

    private function renderFrontend(string $template, array $data = []): void
    {
        $data['main_menu']      = Menu::getItems('main');
        $data['main_menu_tree'] = Menu::getItemsTree('main');
        $data['footer_menu']    = Menu::getItems('footer');

        $view = $this->app->service('view');
        $html = $view->render($template, $data);
        Response::html($html);
    }
}
