<?php
/**
 * PlaceholderRenderer Tests
 * Tests for dynamic placeholder resolution with typed output contracts
 */

namespace WooNooW\Tests;

use PHPUnit\Framework\TestCase;
use WooNooW\Frontend\PlaceholderRenderer;

class PlaceholderRendererTest extends TestCase
{
    /**
     * Test get_source_type returns correct types
     */
    public function test_get_source_type()
    {
        $this->assertEquals('scalar', PlaceholderRenderer::get_source_type('post_title'));
        $this->assertEquals('html', PlaceholderRenderer::get_source_type('post_content'));
        $this->assertEquals('url', PlaceholderRenderer::get_source_type('post_featured_image'));
        $this->assertEquals('array', PlaceholderRenderer::get_source_type('post_categories'));
        $this->assertEquals('array', PlaceholderRenderer::get_source_type('related_posts'));
        $this->assertEquals('url', PlaceholderRenderer::get_source_type('post_url'));
    }

    /**
     * Test validate_value_type for scalar values
     */
    public function test_validate_value_type_scalar()
    {
        $this->assertTrue(PlaceholderRenderer::validate_value_type('Hello', 'scalar'));
        $this->assertTrue(PlaceholderRenderer::validate_value_type(123, 'scalar'));
        $this->assertTrue(PlaceholderRenderer::validate_value_type('', 'scalar'));
        $this->assertFalse(PlaceholderRenderer::validate_value_type(['array'], 'scalar'));
    }

    /**
     * Test validate_value_type for URL values
     */
    public function test_validate_value_type_url()
    {
        $this->assertTrue(PlaceholderRenderer::validate_value_type('https://example.com/image.jpg', 'url'));
        $this->assertFalse(PlaceholderRenderer::validate_value_type('', 'url'));
        $this->assertFalse(PlaceholderRenderer::validate_value_type(['array'], 'url'));
    }

    /**
     * Test validate_value_type for array values
     */
    public function test_validate_value_type_array()
    {
        $this->assertTrue(PlaceholderRenderer::validate_value_type(['a', 'b', 'c'], 'array'));
        $this->assertTrue(PlaceholderRenderer::validate_value_type([], 'array'));
        $this->assertFalse(PlaceholderRenderer::validate_value_type('string', 'array'));
    }

    /**
     * Test get_fallback returns correct defaults
     */
    public function test_get_fallback()
    {
        $this->assertEquals('(Untitled)', PlaceholderRenderer::get_fallback('post_title'));
        $this->assertEquals([], PlaceholderRenderer::get_fallback('post_categories', 'array'));
        $this->assertEquals('', PlaceholderRenderer::get_fallback('unknown_source'));
        $this->assertEquals([], PlaceholderRenderer::get_fallback('unknown_source', 'array'));
    }

    /**
     * Test is_array_source identifies array-based sources
     */
    public function test_is_array_source()
    {
        $this->assertTrue(PlaceholderRenderer::is_array_source('post_categories'));
        $this->assertTrue(PlaceholderRenderer::is_array_source('post_tags'));
        $this->assertTrue(PlaceholderRenderer::is_array_source('related_posts'));
        $this->assertFalse(PlaceholderRenderer::is_array_source('post_title'));
        $this->assertFalse(PlaceholderRenderer::is_array_source('post_featured_image'));
    }

    /**
     * Test get_value resolves scalar values
     */
    public function test_get_value_resolves_scalar()
    {
        $post_data = [
            'title' => 'Test Post Title',
            'content' => '<p>Post content here</p>',
            'author' => 'John Doe',
        ];

        $this->assertEquals('Test Post Title', PlaceholderRenderer::get_value('post_title', $post_data));
        $this->assertEquals('<p>Post content here</p>', PlaceholderRenderer::get_value('post_content', $post_data));
        $this->assertEquals('John Doe', PlaceholderRenderer::get_value('post_author', $post_data));
    }

    /**
     * Test get_value resolves URL values
     */
    public function test_get_value_resolves_url()
    {
        $post_data = [
            'featured_image' => 'https://example.com/featured.jpg',
            'url' => 'https://example.com/post',
        ];

        $this->assertEquals('https://example.com/featured.jpg', PlaceholderRenderer::get_value('post_featured_image', $post_data));
        $this->assertEquals('https://example.com/post', PlaceholderRenderer::get_value('post_url', $post_data));
    }

    /**
     * Test get_value with fallback for empty values
     */
    public function test_get_value_with_fallback()
    {
        $post_data = [
            'title' => '',
            'featured_image' => '',
        ];

        $this->assertEquals('(Untitled)', PlaceholderRenderer::get_value('post_title', $post_data));
        $this->assertEquals('', PlaceholderRenderer::get_value('post_featured_image', $post_data));
    }

    /**
     * Test get_value with empty post_data
     */
    public function test_get_value_with_empty_post_data()
    {
        $this->assertEquals('(Untitled)', PlaceholderRenderer::get_value('post_title', []));
        $this->assertEquals('', PlaceholderRenderer::get_value('post_featured_image', []));
        $this->assertEquals([], PlaceholderRenderer::get_value('post_categories', []));
    }

    /**
     * Test get_value with options
     */
    public function test_get_value_with_options()
    {
        $post_data = [
            'title' => '',
        ];

        // Without fallback
        $result = PlaceholderRenderer::get_value('post_title', $post_data, ['use_fallback' => false]);
        $this->assertEquals('', $result);

        // Without type validation
        $result = PlaceholderRenderer::get_value('post_title', $post_data, ['validate_type' => false]);
        $this->assertEquals('(Untitled)', $result);
    }

    /**
     * Test custom meta field resolution
     */
    public function test_get_value_custom_meta_field()
    {
        $post_data = [
            'meta' => [
                'custom_field' => 'Custom Value',
            ],
        ];

        $this->assertEquals('Custom Value', PlaceholderRenderer::get_value('post_field_custom_field', $post_data));
    }

    /**
     * Test build_post_data returns required fields
     */
    public function test_build_post_data_structure()
    {
        global $wpdb;

        // Create a mock WP_Post
        $post = new \stdClass();
        $post->ID = 1;
        $post->post_title = 'Test Title';
        $post->post_content = 'Test Content';
        $post->post_excerpt = 'Test Excerpt';
        $post->post_author = 1;
        $post->post_type = 'post';
        $post->post_name = 'test-title';
        $post->post_date = '2024-01-01 12:00:00';

        // Mock WordPress functions
        if (!function_exists('get_the_date')) {
            function get_the_date() { return 'January 1, 2024'; }
        }
        if (!function_exists('get_permalink')) {
            function get_permalink() { return 'https://example.com/test-title'; }
        }
        if (!function_exists('get_the_author_meta')) {
            function get_the_author_meta() { return 'Admin'; }
        }
        if (!function_exists('get_post_thumbnail_id')) {
            function get_post_thumbnail_id() { return 0; }
        }
        if (!function_exists('get_the_post_thumbnail_url')) {
            function get_the_post_thumbnail_url() { return ''; }
        }
        if (!function_exists('get_object_taxonomies')) {
            function get_object_taxonomies() { return []; }
        }
        if (!function_exists('get_the_terms')) {
            function get_the_terms() { return []; }
        }
        if (!function_exists('get_post_meta')) {
            function get_post_meta() { return []; }
        }
        if (!function_exists('apply_filters')) {
            function apply_filters($tag, $value) { return $value; }
        }
        if (!function_exists('wp_trim_words')) {
            function wp_trim_words($text, $num_words, $more) { return $text; }
        }

        $data = PlaceholderRenderer::build_post_data($post);

        $this->assertArrayHasKey('title', $data);
        $this->assertArrayHasKey('content', $data);
        $this->assertArrayHasKey('url', $data);
        $this->assertArrayHasKey('type', $data);
    }
}