<?php

namespace FleekDash\API\Posts;

use FleekDash\Controllers\Post\PostFormatter;
use WP_Post;

/**
 * Posts Data Mapper
 *
 * Handles mapping WordPress posts to API response format
 * Extracted from FLEEKDASH_Posts_Optimized_API for better organization
 *
 * @package FleekDash\API\Posts
 * @since 2.2.0
 */
class PostsDataMapper
{
    /**
     * Posts data formatter instance
     *
     * @var PostsDataFormatter
     */
    private $formatter;

    /**
     * Constructor
     */
    public function __construct()
    {
        $this->formatter = new PostsDataFormatter();
    }

    /**
     * Map WP_Post to array format
     *
     * @param WP_Post $post WordPress post object
     * @return array Formatted post data
     */
    public function mapPostToArray($post)
    {
        $author_data = $this->getAuthorData($post->post_author);
        $image_data = PostsDataFormatter::getPostImageData($post->ID);
        $taxonomies = $this->getTaxonomiesData($post->ID);
        $stats = $this->getPostStats($post->ID);

        return [
            'id' => $post->ID,
            'title' => $post->post_title,
            'excerpt' => $post->post_excerpt,
            'status' => $post->post_status,
            'type' => $post->post_type,
            'date' => \mysql_to_rfc3339($post->post_date),
            'date_gmt' => PostFormatter::formatPostDateGmtAtom((string) $post->post_date_gmt),
            'modified' => \mysql_to_rfc3339($post->post_modified),
            'date_relative' => PostsDataFormatter::getRelativeTime($post->post_date),
            'modified_relative' => PostsDataFormatter::getRelativeTime($post->post_modified),
            'author' => $author_data,
            'featured_image' => $image_data['url'],
            'featured_image_type' => $image_data['type'],
            'categories' => $taxonomies['categories'] ?? [],
            'tags' => $taxonomies['tags'] ?? [],
            'taxonomies' => $taxonomies,
            'views' => $stats['views'],
            'comments_count' => $stats['comments'],
            'edit_url' => get_edit_post_link($post->ID, 'raw'),
            'permalink' => get_permalink($post->ID),
        ];
    }

    /**
     * Get author data
     *
     * @param int $author_id Author user ID
     * @return array|null Author data or null if not found
     */
    public function getAuthorData($author_id)
    {
        $author = \get_userdata($author_id);

        if (!$author) {
            return null;
        }

        $avatar_url = get_avatar_url($author->ID, ['size' => 96]);

        return [
            'id' => $author->ID,
            'name' => $author->display_name,
            'email' => $author->user_email,
            'avatar' => $avatar_url ?: '',
        ];
    }

    /**
     * Get taxonomies data for a post
     *
     * @param int $post_id Post ID
     * @return array Taxonomies data
     */
    public function getTaxonomiesData($post_id)
    {
        $taxonomies_data = [];

        // Get all taxonomies for this post type
        $post_type = \get_post_type($post_id);
        $taxonomies = get_object_taxonomies($post_type, 'objects');

        foreach ($taxonomies as $taxonomy) {
            $terms = get_the_terms($post_id, $taxonomy->name);

            if (!$terms || is_wp_error($terms)) {
                continue;
            }

            $terms_data = [];
            foreach ($terms as $term) {
                $terms_data[] = [
                    'id' => $term->term_id,
                    'name' => $term->name,
                    'slug' => $term->slug,
                ];
            }

            // Special handling for common taxonomies
            if ($taxonomy->name === 'category') {
                $taxonomies_data['categories'] = $terms_data;
            } elseif ($taxonomy->name === 'post_tag') {
                $taxonomies_data['tags'] = $terms_data;
            } else {
                $taxonomies_data[$taxonomy->name] = $terms_data;
            }
        }

        return $taxonomies_data;
    }

    /**
     * Get post statistics
     *
     * @param int $post_id Post ID
     * @return array Post stats (views, comments)
     */
    public function getPostStats($post_id)
    {
        // Get views count (if plugin installed)
        $views = 0;
        if (function_exists('pvc_get_post_views')) {
            // @phpstan-ignore-next-line - pvc_get_post_views from Post Views Counter plugin
            $views = call_user_func('pvc_get_post_views', $post_id);
        } elseif (metadata_exists('post', $post_id, 'views')) {
            $views = (int) \get_post_meta($post_id, 'views', true);
        }

        // Get comments count
        $comments_count = wp_count_comments($post_id);
        $total_comments = 0;

        if ($comments_count) {
            $total_comments = (int) ($comments_count->approved ?? 0);
        }

        return [
            'views' => $views,
            'comments' => $total_comments,
        ];
    }

    /**
     * Get meta fields for a post
     *
     * @param int $post_id Post ID
     * @param array $meta_keys Meta keys to retrieve (empty = all)
     * @return array Meta fields
     */
    public function getMetaFields($post_id, $meta_keys = [])
    {
        if (empty($meta_keys)) {
            // Get all meta
            $all_meta = \get_post_meta($post_id);

            // Filter out internal WordPress meta (starts with _)
            $public_meta = [];
            foreach ($all_meta as $key => $value) {
                if (strpos($key, '_') !== 0) {
                    $public_meta[$key] = maybe_unserialize($value[0] ?? '');
                }
            }

            return $public_meta;
        }

        // Get specific meta keys
        $meta_data = [];
        foreach ($meta_keys as $key) {
            $meta_data[$key] = \get_post_meta($post_id, $key, true);
        }

        return $meta_data;
    }

    /**
     * Map multiple posts to array
     *
     * @param array $posts Array of WP_Post objects
     * @return array Array of formatted posts
     */
    public function mapPostsToArray($posts)
    {
        if (empty($posts) || !is_array($posts)) {
            return [];
        }

        $formatted_posts = [];

        foreach ($posts as $post) {
            if (!$post instanceof WP_Post) {
                continue;
            }

            $formatted_posts[] = $this->mapPostToArray($post);
        }

        return $formatted_posts;
    }

    /**
     * Build response with pagination metadata
     *
     * @param array $posts Formatted posts array
     * @param int $page Current page
     * @param int $per_page Posts per page
     * @param int $total_posts Total posts found
     * @return array Response with data and metadata
     */
    public function buildResponse($posts, $page, $per_page, $total_posts = null)
    {
        $response = [
            'success' => true,
            'data' => $posts,
            'pagination' => [
                'page' => $page,
                'per_page' => $per_page,
                'total' => count($posts),
            ],
        ];

        // Add total_posts if provided
        if ($total_posts !== null) {
            $response['pagination']['total_posts'] = $total_posts;
            $response['pagination']['total_pages'] = ceil($total_posts / $per_page);
        }

        return $response;
    }
}
