<?php
/**
 * Unit Tests for HVAC Announcements Display Handler
 *
 * @package HVAC_Community_Events
 * @subpackage Tests
 */

class Test_HVAC_Announcements_Display extends WP_UnitTestCase {
    
    /**
     * Test users
     */
    private $master_trainer;
    private $regular_trainer;
    
    /**
     * Test announcements
     */
    private $test_announcements = array();
    
    /**
     * Display handler instance
     */
    private $display_handler;
    
    /**
     * Setup before each test
     */
    public function setUp() {
        parent::setUp();
        
        // Create test users
        $this->master_trainer = $this->factory->user->create( array(
            'role' => 'hvac_master_trainer',
            'user_login' => 'master_trainer',
            'user_email' => 'master@example.com',
        ) );
        
        $this->regular_trainer = $this->factory->user->create( array(
            'role' => 'hvac_trainer',
            'user_login' => 'regular_trainer',
            'user_email' => 'trainer@example.com',
        ) );
        
        // Add capabilities
        HVAC_Announcements_Permissions::add_capabilities();
        
        // Create test announcements with different statuses
        $this->test_announcements['published'] = wp_insert_post( array(
            'post_type' => HVAC_Announcements_CPT::get_post_type(),
            'post_title' => 'Published Announcement',
            'post_content' => 'This is published content.',
            'post_excerpt' => 'Published excerpt',
            'post_status' => 'publish',
            'post_author' => $this->master_trainer,
        ) );
        
        $this->test_announcements['draft'] = wp_insert_post( array(
            'post_type' => HVAC_Announcements_CPT::get_post_type(),
            'post_title' => 'Draft Announcement',
            'post_content' => 'This is draft content.',
            'post_status' => 'draft',
            'post_author' => $this->master_trainer,
        ) );
        
        // Get display handler instance
        $this->display_handler = HVAC_Announcements_Display::get_instance();
    }
    
    /**
     * Teardown after each test
     */
    public function tearDown() {
        parent::tearDown();
        
        // Clean up test announcements
        foreach ( $this->test_announcements as $post_id ) {
            wp_delete_post( $post_id, true );
        }
        
        // Clean up test users
        wp_delete_user( $this->master_trainer );
        wp_delete_user( $this->regular_trainer );
        
        // Remove capabilities
        HVAC_Announcements_Permissions::remove_capabilities();
    }
    
    /**
     * Test shortcode registration
     */
    public function test_shortcodes_registered() {
        global $shortcode_tags;
        
        $this->assertArrayHasKey( 'hvac_announcements_timeline', $shortcode_tags );
        $this->assertArrayHasKey( 'hvac_announcements_list', $shortcode_tags );
        $this->assertArrayHasKey( 'hvac_google_drive_embed', $shortcode_tags );
    }
    
    /**
     * Test timeline shortcode output for authorized user
     */
    public function test_timeline_shortcode_authorized() {
        wp_set_current_user( $this->regular_trainer );
        
        $output = do_shortcode( '[hvac_announcements_timeline posts_per_page="5"]' );
        
        // Should contain the wrapper div
        $this->assertStringContainsString( 'hvac-announcements-timeline', $output );
        
        // Should contain the published announcement
        $this->assertStringContainsString( 'Published Announcement', $output );
        
        // Should NOT contain draft announcement for regular trainer
        $this->assertStringNotContainsString( 'Draft Announcement', $output );
        
        // Should contain modal structure
        $this->assertStringContainsString( 'announcement-modal', $output );
    }
    
    /**
     * Test timeline shortcode output for unauthorized user
     */
    public function test_timeline_shortcode_unauthorized() {
        // Create non-trainer user
        $subscriber = $this->factory->user->create( array(
            'role' => 'subscriber',
        ) );
        
        wp_set_current_user( $subscriber );
        
        $output = do_shortcode( '[hvac_announcements_timeline]' );
        
        // Should show permission denied message
        $this->assertStringContainsString( 'You do not have permission to view announcements', $output );
        
        // Clean up
        wp_delete_user( $subscriber );
    }
    
    /**
     * Test list shortcode attributes
     */
    public function test_list_shortcode_attributes() {
        wp_set_current_user( $this->regular_trainer );
        
        // Test with show_excerpt="no"
        $output = do_shortcode( '[hvac_announcements_list show_excerpt="no" show_date="yes"]' );
        
        // Should contain the list wrapper
        $this->assertStringContainsString( 'hvac-announcements-list', $output );
        
        // Should contain announcement title
        $this->assertStringContainsString( 'Published Announcement', $output );
    }
    
    /**
     * Test Google Drive embed shortcode
     */
    public function test_google_drive_shortcode() {
        wp_set_current_user( $this->regular_trainer );

        $output = do_shortcode( '[hvac_google_drive_embed url="https://drive.google.com/drive/folders/1-SDHGR9Ix6BmUVTHa3wI99K0rwfWL-vs" height="500"]' );

        // Should contain iframe
        $this->assertStringContainsString( '<iframe', $output );
        $this->assertStringContainsString( 'height="500"', $output );

        // Should contain embed URL
        $this->assertStringContainsString( 'embeddedfolderview', $output );
    }
    
    /**
     * Test Google Drive URL conversion
     */
    public function test_drive_url_conversion() {
        $reflection = new ReflectionClass( $this->display_handler );
        $method = $reflection->getMethod( 'convert_drive_url_to_embed' );
        $method->setAccessible( true );

        // Test folder URL conversion
        $sharing_url = 'https://drive.google.com/drive/folders/1-SDHGR9Ix6BmUVTHa3wI99K0rwfWL-vs?usp=drive_link';
        $embed_url = $method->invoke( $this->display_handler, $sharing_url );

        $this->assertEquals( 'https://drive.google.com/embeddedfolderview?id=1-SDHGR9Ix6BmUVTHa3wI99K0rwfWL-vs#list', $embed_url );

        // Test invalid URL returns original
        $invalid_url = 'https://example.com/not-a-drive-url';
        $result = $method->invoke( $this->display_handler, $invalid_url );

        $this->assertEquals( $invalid_url, $result );
    }
    
    /**
     * Test get_announcement_content with permissions
     */
    public function test_get_announcement_content_permissions() {
        // Test as regular trainer viewing published announcement
        wp_set_current_user( $this->regular_trainer );
        $content = HVAC_Announcements_Display::get_announcement_content( $this->test_announcements['published'] );
        
        $this->assertStringContainsString( 'Published Announcement', $content );
        $this->assertStringContainsString( 'This is published content.', $content );
        
        // Test as regular trainer viewing draft announcement (should be empty)
        $content = HVAC_Announcements_Display::get_announcement_content( $this->test_announcements['draft'] );
        $this->assertEmpty( $content );
        
        // Test as master trainer viewing draft announcement
        wp_set_current_user( $this->master_trainer );
        $content = HVAC_Announcements_Display::get_announcement_content( $this->test_announcements['draft'] );
        
        $this->assertStringContainsString( 'Draft Announcement', $content );
    }
    
    /**
     * Test output escaping in get_announcement_content
     */
    public function test_output_escaping() {
        // Create announcement with special characters
        $test_id = wp_insert_post( array(
            'post_type' => HVAC_Announcements_CPT::get_post_type(),
            'post_title' => 'Test & Title with <special> characters',
            'post_content' => 'Content with & and < > characters',
            'post_status' => 'publish',
            'post_author' => $this->master_trainer,
        ) );
        
        wp_set_current_user( $this->regular_trainer );
        $content = HVAC_Announcements_Display::get_announcement_content( $test_id );
        
        // Title should be escaped
        $this->assertStringContainsString( 'Test &amp; Title with &lt;special&gt; characters', $content );
        
        // Clean up
        wp_delete_post( $test_id, true );
    }
    
    /**
     * Test categories and tags display
     */
    public function test_categories_and_tags_display() {
        // Add category and tags to announcement
        $category_id = wp_insert_term( 'Test Category', HVAC_Announcements_CPT::get_category_taxonomy() );
        wp_set_post_terms( 
            $this->test_announcements['published'], 
            array( $category_id['term_id'] ), 
            HVAC_Announcements_CPT::get_category_taxonomy() 
        );
        
        wp_set_post_terms( 
            $this->test_announcements['published'], 
            array( 'tag1', 'tag2' ), 
            HVAC_Announcements_CPT::get_tag_taxonomy() 
        );
        
        wp_set_current_user( $this->regular_trainer );
        $content = HVAC_Announcements_Display::get_announcement_content( $this->test_announcements['published'] );
        
        // Should contain categories and tags
        $this->assertStringContainsString( 'Categories:', $content );
        $this->assertStringContainsString( 'Test Category', $content );
        $this->assertStringContainsString( 'Tags:', $content );
        $this->assertStringContainsString( 'tag1', $content );
        $this->assertStringContainsString( 'tag2', $content );
        
        // Clean up
        wp_delete_term( $category_id['term_id'], HVAC_Announcements_CPT::get_category_taxonomy() );
    }
    
    /**
     * Test singleton pattern
     */
    public function test_singleton_pattern() {
        $instance1 = HVAC_Announcements_Display::get_instance();
        $instance2 = HVAC_Announcements_Display::get_instance();
        
        $this->assertSame( $instance1, $instance2 );
    }
}