<?php
/**
 * DESCRIPTION: Pushes and removes events in Google Calendar when bookings are confirmed or cancelled.
 * Stores the Google Calendar event ID on the booking meta for later deletion.
 *
 * @package NemtlyBooking\Integrations\Google
 */

namespace NemtlyBooking\Integrations\Google;

use Google\Service\Calendar;
use Google\Service\Calendar\Event as GoogleEvent;
use Google\Service\Calendar\EventDateTime;
use NemtlyBooking\Models\Booking;
use NemtlyBooking\Repositories\Event_Repository;

/**
 * Google Calendar Service
 *
 * Handles creating and deleting Google Calendar events in response
 * to Nemtly booking lifecycle hooks.
 *
 * @since PBOOKING_SINCE
 */
class Google_Calendar_Service {

    /**
     * Booking meta key used to store the Google Calendar event ID.
     */
    const GCAL_EVENT_META_KEY = 'google_calendar_event_id';

    /**
     * OAuth provider instance.
     *
     * @var Google_OAuth_Provider
     */
    private $oauth_provider;

    /**
     * Event repository instance.
     *
     * @var Event_Repository
     */
    private $event_repository;

    /**
     * Constructor
     *
     * @since PBOOKING_SINCE
     *
     * @param Google_OAuth_Provider $oauth_provider   OAuth provider instance.
     * @param Event_Repository      $event_repository Event repository instance.
     */
    public function __construct( Google_OAuth_Provider $oauth_provider, Event_Repository $event_repository ) {
        $this->oauth_provider   = $oauth_provider;
        $this->event_repository = $event_repository;
    }

    /**
     * Push a confirmed booking to Google Calendar.
     *
     * @since PBOOKING_SINCE
     *
     * @param array $booking_data Booking data array from the booking confirmed hook.
     *
     * @return void
     */
    public function push_booking( $booking_data ) {
        if ( ! $this->oauth_provider->is_connected() ) {
            return;
        }

        $booking = new Booking( $booking_data );
        $event   = $this->event_repository->find( $booking->get_event_id() );

        if ( ! $event ) {
            return;
        }

        $calendar_id = get_option( Google_OAuth_Provider::CALENDAR_ID_OPTION, 'primary' );
        $client      = $this->oauth_provider->get_client();

        if ( ! $client ) {
            return;
        }

        try {
            $service = new Calendar( $client );

            $google_event = $this->build_google_event( $booking, $event );
            $created      = $service->events->insert( $calendar_id, $google_event );

            // Store the Google Calendar event ID in booking meta so we can delete it later.
            $meta = $booking->get_booking_meta();
            if ( ! is_array( $meta ) ) {
                $meta = [];
            }
            $meta[ self::GCAL_EVENT_META_KEY ] = $created->getId();
            $booking->set_booking_meta( $meta );

            $booking_repo = new \NemtlyBooking\Repositories\Booking_Repository();
            $booking_repo->update( $booking );

        } catch ( \Exception $e ) {
            // Log but do not surface to end users — calendar sync failure must not break booking flow.
            error_log( 'Nemtly Google Calendar push failed: ' . $e->getMessage() );
        }
    }

    /**
     * Delete a cancelled booking from Google Calendar.
     *
     * @since PBOOKING_SINCE
     *
     * @param array $booking_data Booking data array from the booking cancelled hook.
     *
     * @return void
     */
    public function remove_booking( $booking_data ) {
        if ( ! $this->oauth_provider->is_connected() ) {
            return;
        }

        $booking    = new Booking( $booking_data );
        $meta       = $booking->get_booking_meta();
        $gcal_event = is_array( $meta ) && ! empty( $meta[ self::GCAL_EVENT_META_KEY ] )
            ? $meta[ self::GCAL_EVENT_META_KEY ]
            : null;

        if ( ! $gcal_event ) {
            return;
        }

        $calendar_id = get_option( Google_OAuth_Provider::CALENDAR_ID_OPTION, 'primary' );
        $client      = $this->oauth_provider->get_client();

        if ( ! $client ) {
            return;
        }

        try {
            $service = new Calendar( $client );
            $service->events->delete( $calendar_id, $gcal_event );
        } catch ( \Exception $e ) {
            error_log( 'Nemtly Google Calendar delete failed: ' . $e->getMessage() );
        }
    }

    /**
     * Build a Google Calendar Event object from a Nemtly booking + event.
     *
     * @since PBOOKING_SINCE
     *
     * @param Booking                                 $booking Booking model.
     * @param \NemtlyBooking\Models\Event             $event   Event model.
     *
     * @return GoogleEvent
     */
    private function build_google_event( Booking $booking, $event ) {
        $google_event = new GoogleEvent();
        $google_event->setSummary( $event->get_title() );

        $description_parts = [
            /* translators: %s: attendee full name */
            sprintf( __( 'Attendee: %s', 'nemtly-booking' ), $booking->get_attendee_name() ),
            /* translators: %s: attendee email address */
            sprintf( __( 'Email: %s', 'nemtly-booking' ), $booking->get_attendee_email() ),
            /* translators: %s: booking reference UUID */
            sprintf( __( 'Booking Reference: %s', 'nemtly-booking' ), $booking->get_booking_uuid() ),
        ];

        if ( $booking->get_attendee_phone() ) {
            /* translators: %s: attendee phone number */
            $description_parts[] = sprintf( __( 'Phone: %s', 'nemtly-booking' ), $booking->get_attendee_phone() );
        }

        $google_event->setDescription( implode( "\n", $description_parts ) );

        $location = get_post_meta( $event->get_id(), 'nemtly_location', true );
        if ( $location ) {
            $google_event->setLocation( $location );
        }

        // Use booking start/end datetimes when available, otherwise fall back to event date + time.
        $start_datetime = $booking->get_booking_start();
        $end_datetime   = $booking->get_booking_end();

        if ( $start_datetime && $end_datetime ) {
            $start = new EventDateTime();
            $start->setDateTime( gmdate( 'c', strtotime( $start_datetime ) ) );
            $start->setTimeZone( wp_timezone_string() );

            $end = new EventDateTime();
            $end->setDateTime( gmdate( 'c', strtotime( $end_datetime ) ) );
            $end->setTimeZone( wp_timezone_string() );
        } else {
            // Fall back to event date + time metadata for all-day or legacy events.
            $event_date = get_post_meta( $event->get_id(), 'nemtly_event_date', true );
            $event_time = get_post_meta( $event->get_id(), 'nemtly_event_time', true );

            $start_str = $event_date . ( $event_time ? 'T' . $event_time . ':00' : '' );

            $start = new EventDateTime();
            $start->setDateTime( gmdate( 'c', strtotime( $start_str ) ) );
            $start->setTimeZone( wp_timezone_string() );

            // Default duration: 1 hour.
            $end = new EventDateTime();
            $end->setDateTime( gmdate( 'c', strtotime( $start_str ) + HOUR_IN_SECONDS ) );
            $end->setTimeZone( wp_timezone_string() );
        }

        $google_event->setStart( $start );
        $google_event->setEnd( $end );

        return apply_filters( 'nemtly_google_calendar_event', $google_event, $booking, $event );
    }
}
