<?php

namespace FleekDash\Controllers\Post;

use FleekDash\Core\AuthMiddleware;
use FleekDash\Libs\API\ResponseService;

/**
 * Handles post creation logic extracted from PostController.
 *
 * @package FleekDash\Controllers\Post
 */
class PostStoreHandler
{
    /**
     * Execute post creation. Returns REST response.
     *
     * @param \WP_REST_Request $request
     * @return \WP_REST_Response
     */
    public static function execute(\WP_REST_Request $request): \WP_REST_Response
    {
        $auth_result = AuthMiddleware::check('authenticated');
        $post_type = $request->get_param('post_type') ?? 'post';

        $error = self::validateRequest($auth_result, $post_type);
        if ($error !== null) {
            return $error;
        }

        $post_data = self::buildPostData($request, $post_type);
        $post_id = \wp_insert_post($post_data, true);

        if (is_wp_error($post_id)) {
            return ResponseService::error('Failed to create post: ' . $post_id->get_error_message(), null, 400);
        }

        self::applyTaxonomies($post_id, $request);
        self::applyMeta($post_id, $request);

        $post = \get_post($post_id);
        return ResponseService::success(PostFormatter::formatPostForGrid($post), 'Post created successfully', 201);
    }

    private static function validateRequest(array $auth_result, string $post_type): ?\WP_REST_Response
    {
        if (!\post_type_exists($post_type)) {
            return ResponseService::error("Invalid post type: {$post_type}", null, 400);
        }
        if ($auth_result['authenticated'] && !\current_user_can("edit_{$post_type}s") && !\current_user_can('manage_options')) {
            return ResponseService::error("You don't have permission to create this post type", null, 403);
        }
        return null;
    }

    /**
     * @return array<string, mixed>
     */
    private static function buildPostData(\WP_REST_Request $request, string $post_type): array
    {
        $post_data = [
            'post_title' => $request->get_param('title'),
            'post_content' => $request->get_param('content'),
            'post_status' => $request->get_param('status') ?? 'draft',
            'post_type' => $post_type,
        ];
        if ($request->get_param('excerpt')) {
            $post_data['post_excerpt'] = $request->get_param('excerpt');
        }
        if ($request->get_param('author')) {
            $post_data['post_author'] = $request->get_param('author');
        }
        return $post_data;
    }

    private static function applyTaxonomies(int $post_id, \WP_REST_Request $request): void
    {
        $taxonomies = $request->get_param('taxonomies');
        if (empty($taxonomies) || !is_array($taxonomies)) {
            return;
        }
        foreach ($taxonomies as $taxonomy => $terms) {
            if (!empty($terms)) {
                wp_set_object_terms($post_id, $terms, $taxonomy);
            }
        }
    }

    private static function applyMeta(int $post_id, \WP_REST_Request $request): void
    {
        $meta = $request->get_param('meta');
        if (empty($meta) || !is_array($meta)) {
            return;
        }
        foreach ($meta as $meta_key => $meta_value) {
            if (strpos($meta_key, '_') === 0) {
                continue;
            }
            $processed = self::processMetaForCreate($meta_key, $meta_value);
            \update_post_meta($post_id, $meta_key, $processed);
        }
    }

    /**
     * Process meta value for create (matches original store behavior for Voxel).
     *
     * @param string $meta_key
     * @param mixed $meta_value
     * @return mixed
     */
    private static function processMetaForCreate(string $meta_key, $meta_value)
    {
        $result = null;
        if (strpos($meta_key, 'voxel:') === 0) {
            if (is_array($meta_value) || is_object($meta_value)) {
                $result = json_encode($meta_value);
            } elseif (is_string($meta_value)) {
                $decoded = json_decode($meta_value, true); // NOSONAR php:S1854 - assign for clarity; we use json_last_error() to validate
                $result = (json_last_error() === JSON_ERROR_NONE) ? $meta_value : json_encode($meta_value);
            } else {
                $result = json_encode($meta_value);
            }
        } elseif (is_string($meta_value) && !empty($meta_value)) {
            $decoded = json_decode($meta_value, true);
            $result = (json_last_error() === JSON_ERROR_NONE && is_array($decoded)) ? $decoded : null;
        }
        return $result ?? PostMetaProcessor::processMetaFieldValue($meta_key, $meta_value);
    }
}
