<?php
/**
 * Unit tests for Event Summary Data functionality
 */

require_once dirname(__DIR__) . '/bootstrap.php';
require_once dirname(__DIR__) . '/test-doubles.php';

/**
 * Class Test_Event_Summary_Data
 *
 * Tests the data retrieval logic for the Event Summary page.
 */
class Test_Event_Summary_Data extends WP_UnitTestCase {

    /**
     * Set up the test environment.
     */
    public function set_up(): void {
        parent::set_up();
        // Include necessary files or setup data factories if needed
        // Use a more robust method to determine the plugin directory
        $plugin_dir = dirname( dirname( __DIR__ ) ) . '/';
        require_once $plugin_dir . 'includes/community/class-event-summary-data.php';
    }

    /**
     * Tear down the test environment.
     */
    public function tear_down(): void {
        parent::tear_down();
    }

    /**
     * Test fetching basic event details.
     * @test
     */
    public function test_get_event_details() {
        // Ensure TEC post type exists
        if ( ! post_type_exists( Tribe__Events__Main::POSTTYPE ) ) {
             $this->markTestSkipped('The Events Calendar post type does not exist.');
        }

        $start_date = '2025-05-10 09:00:00';
        $end_date   = '2025-05-10 17:00:00';
        $cost       = '50.00';
        $event_id   = self::factory()->post->create( [
            'post_type'    => Tribe__Events__Main::POSTTYPE,
            'post_title'   => 'Test Event Summary',
            'post_content' => 'This is the event description.',
            'post_excerpt' => 'Short description.',
            'post_status'  => 'publish',
        ] );

        // Set TEC meta data
        update_post_meta( $event_id, '_EventStartDate', $start_date );
        update_post_meta( $event_id, '_EventEndDate', $end_date );
        update_post_meta( $event_id, '_EventCost', $cost );
        update_post_meta( $event_id, '_EventCurrencySymbol', '$' ); // Assuming USD
        update_post_meta( $event_id, '_EventAllDay', 'no' );
        update_post_meta( $event_id, '_EventShowMapLink', 'true' );
        update_post_meta( $event_id, '_EventShowMap', 'true' );
        // Add other meta as needed for tribe_ functions to work

        $summary_data = new HVAC_Event_Summary_Data( $event_id );
        $details      = $summary_data->get_event_details();

        $this->assertIsArray( $details );
        $this->assertEquals( $event_id, $details['id'] );
        $this->assertEquals( 'Test Event Summary', $details['title'] );
        $this->assertEquals( '<p>This is the event description.</p>', trim( $details['description'] ) ); // WP adds <p> tags via filter
        $this->assertEquals( 'Short description.', $details['excerpt'] );
        $this->assertEquals( get_permalink( $event_id ), $details['permalink'] );

        // Check TEC function results (if functions exist)
        if ( function_exists( 'tribe_get_start_date' ) ) {
            $this->assertEquals( $start_date, $details['start_date'] );
        }
         if ( function_exists( 'tribe_get_end_date' ) ) {
            $this->assertEquals( $end_date, $details['end_date'] );
        }
         if ( function_exists( 'tribe_get_cost' ) ) {
            // tribe_get_cost() returns formatted cost with currency symbol
            $formatted_cost = tribe_get_cost( $event_id, true );
            $this->assertEquals( $formatted_cost, $details['cost'] );
        }
         if ( function_exists( 'tribe_event_is_all_day' ) ) {
            $this->assertFalse( $details['is_all_day'] );
        }
         if ( function_exists( 'tribe_is_recurring_event' ) ) {
             $this->assertFalse( $details['is_recurring'] ); // Assuming not recurring by default
        }
         if ( function_exists( 'tribe_get_timezone' ) ) {
             $this->assertNotEmpty( $details['timezone'] ); // Should default to WP timezone
        }
    }

    /**
     * Test fetching event venue details.
     * @test
     */
    public function test_get_event_venue_details() {
        // Ensure TEC post types exist
        if ( ! post_type_exists( Tribe__Events__Main::POSTTYPE ) || ! post_type_exists( Tribe__Events__Main::VENUE_POST_TYPE ) ) {
             $this->markTestSkipped('The Events Calendar post types (event/venue) do not exist.');
        }
         // Ensure TEC functions exist for checking later
        if ( ! function_exists( 'tribe_get_venue_id' ) || ! function_exists( 'tribe_get_venue' ) ) {
             $this->markTestSkipped('Required TEC venue functions do not exist.');
        }

        // 1. Create Venue
        $venue_data = [
            'Venue'     => 'Test Venue Name',
            'Address'   => '123 Test St',
            'City'      => 'Testville',
            'State'     => 'TS', // Use State for US, Province otherwise
            'Province'  => '',
            'Zip'       => '12345',
            'Country'   => 'United States',
            'Phone'     => '555-1234',
            'URL'       => 'http://example.com/venue'
        ];
        $venue_id = self::factory()->post->create( [
            'post_type'   => Tribe__Events__Main::VENUE_POST_TYPE,
            'post_title'  => $venue_data['Venue'],
            'post_status' => 'publish',
        ] );
        // Explicitly set known meta keys used by tribe_get_* functions
        update_post_meta( $venue_id, '_VenueAddress', $venue_data['Address'] );
        update_post_meta( $venue_id, '_VenueCity', $venue_data['City'] );
        update_post_meta( $venue_id, '_VenueStateProvince', $venue_data['State'] ); // This is the key tribe_get_stateprovince uses
        update_post_meta( $venue_id, '_VenueState', $venue_data['State'] );         // Also set _VenueState just in case
        update_post_meta( $venue_id, '_VenueProvince', $venue_data['Province'] );
        update_post_meta( $venue_id, '_VenueZip', $venue_data['Zip'] );
        update_post_meta( $venue_id, '_VenueCountry', $venue_data['Country'] );
        update_post_meta( $venue_id, '_VenuePhone', $venue_data['Phone'] );
        update_post_meta( $venue_id, '_VenueURL', $venue_data['URL'] );

        // 2. Create Event linked to Venue
        $event_id_with_venue = self::factory()->post->create( [
            'post_type'   => Tribe__Events__Main::POSTTYPE,
            'post_title'  => 'Event With Venue',
            'post_status' => 'publish',
        ] );
        update_post_meta( $event_id_with_venue, '_EventVenueID', $venue_id );

        // 3. Test retrieval for event with venue
        $summary_data_with_venue = new HVAC_Event_Summary_Data( $event_id_with_venue );
        $details_with_venue      = $summary_data_with_venue->get_event_venue_details();

        $this->assertIsArray( $details_with_venue );
        $this->assertEquals( $venue_id, $details_with_venue['id'] );
        $this->assertEquals( $venue_data['Venue'], $details_with_venue['name'] );
        $this->assertStringContainsString( $venue_data['Address'], $details_with_venue['address'] ); // tribe_get_full_address combines fields
        $this->assertEquals( $venue_data['Address'], $details_with_venue['street'] );
        $this->assertEquals( $venue_data['City'], $details_with_venue['city'] );
        $this->assertEquals( $venue_data['State'], $details_with_venue['stateprovince'] );
        $this->assertEquals( $venue_data['State'], $details_with_venue['state'] );
        $this->assertEquals( $venue_data['Zip'], $details_with_venue['zip'] );
        $this->assertEquals( $venue_data['Country'], $details_with_venue['country'] );
        $this->assertEquals( $venue_data['Phone'], $details_with_venue['phone'] );
        // tribe_get_venue_website_link() returns the full HTML link
        $expected_venue_website_html = tribe_get_venue_website_link( $venue_id );
        $this->assertEquals( $expected_venue_website_html, $details_with_venue['website'] );
        $this->assertNotNull( $details_with_venue['map_link'] ); // Check if link is generated

        // 4. Create Event without Venue
         $event_id_no_venue = self::factory()->post->create( [
            'post_type'   => Tribe__Events__Main::POSTTYPE,
            'post_title'  => 'Event Without Venue',
            'post_status' => 'publish',
        ] );
         update_post_meta( $event_id_no_venue, '_EventVenueID', 0 ); // Explicitly set to 0 or non-existent ID

        // 5. Test retrieval for event without venue
        $summary_data_no_venue = new HVAC_Event_Summary_Data( $event_id_no_venue );
        $details_no_venue      = $summary_data_no_venue->get_event_venue_details();

        $this->assertNull( $details_no_venue );
    }

    /**
     * Test fetching event organizer details.
     * @test
     */
    public function test_get_event_organizer_details() {
         // Ensure TEC post types exist
        if ( ! post_type_exists( Tribe__Events__Main::POSTTYPE ) || ! post_type_exists( Tribe__Events__Main::ORGANIZER_POST_TYPE ) ) {
             $this->markTestSkipped('The Events Calendar post types (event/organizer) do not exist.');
        }
        // Ensure TEC functions exist for checking later
        if ( ! function_exists( 'tribe_get_organizer_ids' ) || ! function_exists( 'tribe_get_organizer' ) ) {
             $this->markTestSkipped('Required TEC organizer functions do not exist.');
        }

        // 1. Create Organizer
        $organizer_data = [
            'Organizer' => 'Test Organizer Inc.',
            'Phone'     => '555-5678',
            'Website'   => 'http://example.com/organizer',
            'Email'     => 'organizer@example.com',
        ];
         $organizer_id = self::factory()->post->create( [
            'post_type'   => Tribe__Events__Main::ORGANIZER_POST_TYPE,
            'post_title'  => $organizer_data['Organizer'],
            'post_status' => 'publish',
        ] );
        foreach ( $organizer_data as $key => $value ) {
             update_post_meta( $organizer_id, '_Organizer' . $key, $value );
        }

        // 2. Create Event linked to Organizer
        $event_id_with_organizer = self::factory()->post->create( [
            'post_type'   => Tribe__Events__Main::POSTTYPE,
            'post_title'  => 'Event With Organizer',
            'post_status' => 'publish',
        ] );
        // Link using the meta key TEC uses
        update_post_meta( $event_id_with_organizer, '_EventOrganizerID', $organizer_id );

        // 3. Test retrieval for event with organizer
        $summary_data_with_organizer = new HVAC_Event_Summary_Data( $event_id_with_organizer );
        $details_with_organizer      = $summary_data_with_organizer->get_event_organizer_details();

        $this->assertIsArray( $details_with_organizer );
        $this->assertEquals( $organizer_id, $details_with_organizer['id'] );
        $this->assertEquals( $organizer_data['Organizer'], $details_with_organizer['name'] );
        $this->assertEquals( $organizer_data['Phone'], $details_with_organizer['phone'] );
        // tribe_get_organizer_website_link() returns the full HTML link
        $expected_website_html = tribe_get_organizer_website_link( $organizer_id );
        $this->assertEquals( $expected_website_html, $details_with_organizer['website'] );
        // tribe_get_organizer_email() might encode entities
        $this->assertEquals( $organizer_data['Email'], html_entity_decode( $details_with_organizer['email'] ) );
        // get_permalink() in test environment might add encoded slash
        $expected_permalink = get_permalink( $organizer_id );
        // Handle potential trailing slash inconsistency
        $this->assertEquals( rtrim($expected_permalink, '/'), rtrim(str_replace('%2F', '/', $details_with_organizer['permalink']), '/') );


        // 4. Create Event without Organizer
        $event_id_no_organizer = self::factory()->post->create( [
            'post_type'   => Tribe__Events__Main::POSTTYPE,
            'post_title'  => 'Event Without Organizer',
            'post_status' => 'publish',
        ] );
        // Ensure no organizer ID is set, or set to 0
        delete_post_meta( $event_id_no_organizer, '_EventOrganizerID' );

        // 5. Test retrieval for event without organizer
        $summary_data_no_organizer = new HVAC_Event_Summary_Data( $event_id_no_organizer );
        $details_no_organizer      = $summary_data_no_organizer->get_event_organizer_details();

        $this->assertNull( $details_no_organizer );
    }

    /**
     * Test fetching data for an event that does not exist.
     * @test
     */
    public function test_get_data_for_nonexistent_event() {
        $invalid_event_id = 999999; // An ID that is unlikely to exist

        $summary_data = new HVAC_Event_Summary_Data( $invalid_event_id );

        // Check constructor handled it
        $this->assertFalse( $summary_data->is_valid_event() );

        // Check data retrieval methods
        $this->assertNull( $summary_data->get_event_details(), 'Details should be null for invalid event' );
        $this->assertNull( $summary_data->get_event_venue_details(), 'Venue details should be null for invalid event' );
        $this->assertNull( $summary_data->get_event_organizer_details(), 'Organizer details should be null for invalid event' );
        $this->assertIsArray( $summary_data->get_event_transactions(), 'Transactions should be an empty array for invalid event' );
        $this->assertEmpty( $summary_data->get_event_transactions(), 'Transactions should be an empty array for invalid event' );
    }
}