<?php
/**
 * Search Preview Controller
 *
 * Handles detailed preview data extraction for search results
 *
 * @package FleekDash\Controllers
 */

namespace FleekDash\Controllers;

use FleekDash\Utils\AvatarHelper;
use WP_Error;
use WP_REST_Request;

class SearchPreviewController extends BaseController
{
    /**
     * Get detailed preview data for an item
     *
     * @param WP_REST_Request $request
     * @return \WP_REST_Response|WP_Error
     */
    public function getPreview(WP_REST_Request $request)
    {
        try {
            return $this->buildPreviewRestResponse($request);
        } catch (\Exception $e) {
            if (\function_exists('fleekdash_log_error')) {
                \fleekdash_log_error('FleekDash Preview Error: ' . $e->getMessage());
            }

            return new WP_Error(
                'preview_error',
                'An error occurred while getting preview',
                ['status' => 500],
            );
        }
    }

    /**
     * @return \WP_REST_Response|WP_Error
     */
    private function buildPreviewRestResponse(WP_REST_Request $request)
    {
        $validated = $this->validateAndExtractPreviewRequest($request);
        if ($validated instanceof WP_Error) {
            return $validated;
        }

        [$type, $id] = $validated;

        $cache_service = new \FleekDash\Services\SearchCacheService();
        $cache_key = "preview_{$type}_{$id}";
        $cached_preview = $cache_service->getCachedPreview($cache_key);

        $response = null;
        if ($cached_preview !== null && $cached_preview !== false) {
            $response = \rest_ensure_response([
                'preview' => $cached_preview,
                'cache_hit' => true,
            ]);
        } else {
            $preview_data = $this->getPreviewData($type, $id);
            if (!$preview_data) {
                $response = new WP_Error(
                    'not_found',
                    'Item not found',
                    ['status' => 404],
                );
            } else {
                $cache_service->cachePreview($cache_key, $preview_data);
                $response = \rest_ensure_response([
                    'preview' => $preview_data,
                    'cache_hit' => false,
                ]);
            }
        }

        return $response;
    }

    /**
     * @return WP_Error|array{0: string, 1: int}
     */
    private function validateAndExtractPreviewRequest(WP_REST_Request $request)
    {
        $type = \sanitize_text_field($request->get_param('type'));
        $id = (int) $request->get_param('id');

        $system_types = ['user', 'menu', 'setting'];
        $is_system_type = \in_array($type, $system_types, true);
        $is_post_type = \post_type_exists($type);

        if (!$is_system_type && !$is_post_type) {
            return new WP_Error(
                'invalid_type',
                'Invalid type specified - must be a valid post type or system type',
                ['status' => 400],
            );
        }

        if ($id < 1) {
            return new WP_Error(
                'invalid_id',
                'Invalid ID specified',
                ['status' => 400],
            );
        }

        return [$type, $id];
    }

    /**
     * @param string $type
     * @param int    $id
     * @return array<string, mixed>|null
     */
    private function getPreviewData(string $type, int $id)
    {
        $data = null;
        switch ($type) {
            case 'user':
                $data = $this->getUserPreview($id);
                break;
            case 'menu':
                $data = $this->getMenuPreview($id);
                break;
            case 'setting':
                $data = $this->getSettingPreview($id);
                break;
            default:
                $data = \post_type_exists($type) ? $this->getPostPreview($id, $type) : null;
                break;
        }

        return $data;
    }

    /**
     * @param string|null $post_type
     * @return array<string, mixed>|null
     */
    private function getPostPreview(int $id, ?string $post_type = null)
    {
        $post = \get_post($id);
        if (!$post || ($post_type && $post->post_type !== $post_type)) {
            return null;
        }

        $author = \get_userdata($post->post_author);
        $categories = \get_the_category($id);
        $tags = \get_the_tags($id);

        $image_data = $this->getPostImageData($id);
        $featured_image = $image_data['url'];

        $wp_featured_image = '';
        if (\has_post_thumbnail($id)) {
            $wp_featured_image = \get_the_post_thumbnail_url($id, 'medium');
        }

        $thumbnail_48 = $this->getBestThumb48($id);

        return [
            'type' => 'post',
            'title' => $post->post_title,
            'content' => \wp_trim_words(\strip_tags($post->post_content), 50),
            'author' => $author ? $author->display_name : 'Unknown',
            'date' => $post->post_date,
            'image' => $featured_image ?: null,
            'thumbnail' => $thumbnail_48 ?: null,
            'featured_image' => $wp_featured_image ?: null,
            'tags' => $tags ? \array_map(static function ($tag) {
                return $tag->name;
            }, $tags) : [],
            'categories' => $categories ? \array_map(static function ($cat) {
                return $cat->name;
            }, $categories) : [],
            'url' => \get_permalink($id),
            'edit_url' => \get_edit_post_link($id),
        ];
    }

    /**
     * @return array<string, mixed>|null
     */
    private function getUserPreview(int $id)
    {
        $user = \get_userdata($id);
        if (!$user) {
            return null;
        }

        return [
            'type' => 'user',
            'name' => $user->display_name,
            'username' => '@' . $user->user_login,
            'email' => $user->user_email,
            'role' => \implode(', ', $user->roles),
            'avatar' => AvatarHelper::getUserAvatarUrl($id, ['size' => 128]),
            'avatar_url' => AvatarHelper::getUserAvatarUrl($id, ['size' => 128]),
            'description' => \get_user_meta($id, 'description', true),
            'url' => \get_author_posts_url($id),
        ];
    }

    /**
     * @return array<string, mixed>|null
     */
    private function getMenuPreview(int $id)
    {
        $menu = \wp_get_nav_menu_object($id);
        if (!$menu) {
            return null;
        }

        $items = \wp_get_nav_menu_items($id);
        $item_count = \is_array($items) ? \count($items) : 0;

        return [
            'type' => 'menu',
            'name' => $menu->name,
            'description' => $menu->description ?: "Navigation menu with {$item_count} items",
            'item_count' => $item_count,
            'locations' => \get_nav_menu_locations(),
        ];
    }

    /**
     * @return array<string, mixed>|null
     */
    private function getSettingPreview(int $id)
    {
        $settings_map = [
            1 => ['name' => 'General Settings', 'section' => 'General', 'icon' => 'settings'],
            2 => ['name' => 'Reading Settings', 'section' => 'Reading', 'icon' => 'book'],
            3 => ['name' => 'Discussion Settings', 'section' => 'Discussion', 'icon' => 'message-circle'],
            4 => ['name' => 'Media Settings', 'section' => 'Media', 'icon' => 'image'],
        ];

        if (!isset($settings_map[$id])) {
            return null;
        }

        $setting = $settings_map[$id];

        return [
            'type' => 'setting',
            'name' => $setting['name'],
            'section' => $setting['section'],
            'icon' => $setting['icon'],
            'url' => \admin_url('options-' . \strtolower($setting['section']) . '.php'),
        ];
    }

    /**
     * @return array{url: string, type: string}
     */
    private function getPostImageData(int $post_id)
    {
        $resolved = $this->resolvePostLogoImage($post_id)
            ?? $this->resolvePostFeaturedImage($post_id)
            ?? $this->resolveFirstAttachedPostImage($post_id);

        return $resolved ?? ['url' => '', 'type' => 'none'];
    }

    /**
     * @return array{url: string, type: string}|null
     */
    private function resolvePostLogoImage(int $post_id)
    {
        $out = null;
        $logo_id = (int) \get_post_meta($post_id, 'logo', true);
        if ($logo_id > 0) {
            $url = $this->resolveSmallestAttachmentUrl($logo_id);
            if ($url !== '') {
                $out = ['url' => $url, 'type' => 'logo'];
            }
        }

        return $out;
    }

    /**
     * @return array{url: string, type: string}|null
     */
    private function resolvePostFeaturedImage(int $post_id)
    {
        $out = null;
        if (\has_post_thumbnail($post_id)) {
            $thumb_id = (int) \get_post_thumbnail_id($post_id);
            if ($thumb_id > 0) {
                $url = $this->resolveSmallestAttachmentUrl($thumb_id);
                if ($url !== '') {
                    $out = ['url' => $url, 'type' => 'featured'];
                }
            }
        }

        return $out;
    }

    /**
     * @return array{url: string, type: string}|null
     */
    private function resolveFirstAttachedPostImage(int $post_id)
    {
        $out = null;
        $attached = \get_attached_media('image', $post_id);
        if (!empty($attached)) {
            $first = \reset($attached);
            if (!empty($first->ID)) {
                $url = $this->resolveSmallestAttachmentUrl((int) $first->ID);
                if ($url !== '') {
                    $out = ['url' => $url, 'type' => 'attached'];
                }
            }
        }

        return $out;
    }

    private function resolveSmallestAttachmentUrl(int $attachment_id): string
    {
        $result = '';
        if ($attachment_id < 1) {
            return $result;
        }

        $url = \wp_get_attachment_image_url($attachment_id, 'fleekdash-preview');
        if ($url) {
            $result = $url;
        } else {
            foreach (['medium_large', 'large', 'medium', 'thumbnail'] as $size) {
                $url = \wp_get_attachment_image_url($attachment_id, $size);
                if ($url) {
                    $result = $url;
                    break;
                }
            }
            if ($result === '') {
                $fallback = \wp_get_attachment_url($attachment_id);
                $result = $fallback ?: '';
            }
        }

        return $result;
    }

    private function getBestThumb48(int $post_id): string
    {
        $candidate_ids = [];

        $logo_id = (int) \get_post_meta($post_id, 'logo', true);
        if ($logo_id > 0) {
            $candidate_ids[] = $logo_id;
        }

        if (\has_post_thumbnail($post_id)) {
            $thumb_id = (int) \get_post_thumbnail_id($post_id);
            if ($thumb_id > 0) {
                $candidate_ids[] = $thumb_id;
            }
        }

        $attached = \get_attached_media('image', $post_id);
        if (!empty($attached)) {
            $first = \reset($attached);
            if (!empty($first->ID)) {
                $candidate_ids[] = (int) $first->ID;
            }
        }

        foreach ($candidate_ids as $attachment_id) {
            $url = $this->resolvePreviewThumbUrl($attachment_id);
            if ($url !== '') {
                return $url;
            }
        }

        return '';
    }

    private function resolvePreviewThumbUrl(int $attachment_id): string
    {
        $result = '';
        if ($attachment_id < 1) {
            return $result;
        }

        $url = \wp_get_attachment_image_url($attachment_id, 'fleekdash-thumbnail');
        if ($url) {
            $result = $url;
        } else {
            foreach (['thumbnail', 'medium', 'medium_large', 'large'] as $size) {
                $url = \wp_get_attachment_image_url($attachment_id, $size);
                if ($url) {
                    $result = $url;
                    break;
                }
            }
            if ($result === '') {
                $fallback = \wp_get_attachment_url($attachment_id);
                $result = $fallback ?: '';
            }
        }

        return $result;
    }
}
