<?php
/**
 * Event model
 *
 * @package NemtlyBooking
 */

namespace NemtlyBooking\Models;

class Event {
    /**
     * Event ID
     *
     * @var int
     */
    private $id;

    /**
     * Event title
     *
     * @var string
     */
    private $title;

    /**
     * Event description
     *
     * @var string
     */
    private $description;

    /**
     * Event date
     *
     * @var string
     */
    private $date;

    /**
     * Event time
     *
     * @var string
     */
    private $time;

    /**
     * Event end date
     *
     * @var string
     */
    private $end_date;

    /**
     * Event end time
     *
     * @var string
     */
    private $end_time;

    /**
     * Event date in UTC
     *
     * @var string
     */
    private $date_utc;

    /**
     * Event time in UTC
     *
     * @var string
     */
    private $time_utc;

    /**
     * Event end date in UTC
     *
     * @var string
     */
    private $end_date_utc;

    /**
     * Event end time in UTC
     *
     * @var string
     */
    private $end_time_utc;

    /**
     * Event timezone (IANA string, e.g. America/New_York)
     *
     * @var string
     */
    private $timezone;

    /**
     * Event duration in minutes
     *
     * @var int
     */
    private $duration;

    /**
     * Event location
     *
     * @var string
     */
    private $location;

    /**
     * Maximum attendees allowed
     *
     * @var int
     */
    private $max_attendees;

    /**
     * Booking cutoff time in hours
     *
     * @var int
     */
    private $booking_cutoff;

    /**
     * Allow waitlist
     *
     * @var bool
     */
    private $allow_waitlist;

    /**
     * Recurrence pattern
     *
     * @var string
     */
    private $recurrence_pattern;

    /**
     * Recurrence count
     *
     * @var int
     */
    private $recurrence_count;

    /**
     * Recurrence end date
     *
     * @var string
     */
    private $recurrence_end;

    /**
     * Parent event ID for recurring events
     *
     * @var int
     */
    private $parent_event_id;

    /**
     * Is recurring event
     *
     * @var bool
     */
    private $is_recurring;

    /**
     * Event status
     *
     * @var string
     */
    private $status;

    /**
     * Event type
     *
     * @var string
     */
    private $event_type;

    /**
     * Availability schedule (keyed by day, each an array of time blocks)
     *
     * @var array
     */
    private $availability;

    /**
     * Buffer time in minutes before the event
     *
     * @var int
     */
    private $buffer_before;

    /**
     * Buffer time in minutes after the event
     *
     * @var int
     */
    private $buffer_after;

    /**
     * Event price
     *
     * @var float
     */
    private $price;

    /**
     * Managed featured image ID or URL
     *
     * @var string|int
     */
    private $featured_image;

    /**
     * Per-event styling tokens (header_background, header_title_text, tag_text, tag_background, detail_text, price_text, button_background, button_text, card_background, border_color, card_radius, button_radius, shadow, spacing, heading_size, heading_weight).
     *
     * Empty values mean "inherit the host theme / plugin default".
     *
     * @since PBOOKING_SINCE
     *
     * @var array
     */
    private $styling;



    /**
     * Constructor
     *
     * @param array $args Event data.
     *
     * @type int    $id                 The event ID.
     * @type string $title              The event title.
     * @type string $description        The event description.
     * @type string $date               The event date.
     * @type string $time               The event time.
     * @type int    $duration           The event duration.
     * @type string $location           The event location.
     * @type int    $max_attendees      The maximum number of attendees.
     * @type int    $booking_cutoff     The booking cutoff time in hours.
     * @type bool   $allow_waitlist     Whether to allow waitlist.
     * @type string $recurrence_pattern The recurrence pattern.
     * @type int    $recurrence_count   The recurrence count.
     * @type string $recurrence_end     The recurrence end date.
     * @type int    $parent_event_id    The parent event ID.
     * @type bool   $is_recurring       Whether this is a recurring event.
     * @type string $status             The event status.
     * @type string $event_type         The event type.
     * @type int    $buffer_before      Minutes blocked before the event start.
     * @type int    $buffer_after       Minutes blocked after the event end.
     */
    public function __construct( $args = [] ) {
        $this->id                 = ! empty( $args['id'] ) ? $args['id'] : 0;
        $this->title              = ! empty( $args['title'] ) ? $args['title'] : '';
        $this->description        = ! empty( $args['description'] ) ? $args['description'] : '';
        $this->date               = ! empty( $args['date'] ) ? $args['date'] : '';
        $this->time               = ! empty( $args['time'] ) ? $args['time'] : '';
        $this->end_date           = ! empty( $args['end_date'] ) ? $args['end_date'] : '';
        $this->end_time           = ! empty( $args['end_time'] ) ? $args['end_time'] : '';
        $this->date_utc           = ! empty( $args['date_utc'] ) ? $args['date_utc'] : '';
        $this->time_utc           = ! empty( $args['time_utc'] ) ? $args['time_utc'] : '';
        $this->end_date_utc       = ! empty( $args['end_date_utc'] ) ? $args['end_date_utc'] : '';
        $this->end_time_utc       = ! empty( $args['end_time_utc'] ) ? $args['end_time_utc'] : '';
        $this->timezone           = ! empty( $args['timezone'] ) ? $args['timezone'] : \wp_timezone_string();
        $this->duration           = ! empty( $args['duration'] ) ? (int) $args['duration'] : 60;
        $this->location           = ! empty( $args['location'] ) ? $args['location'] : '';
        $this->max_attendees      = ! empty( $args['max_attendees'] ) ? (int) $args['max_attendees'] : 0;
        $this->booking_cutoff     = ! empty( $args['booking_cutoff'] ) ? (int) $args['booking_cutoff'] : 0;
        $this->allow_waitlist     = ! empty( $args['allow_waitlist'] ) ? (bool) $args['allow_waitlist'] : false;
        $this->recurrence_pattern = ! empty( $args['recurrence_pattern'] ) ? $args['recurrence_pattern'] : 'none';
        $this->recurrence_count   = ! empty( $args['recurrence_count'] ) ? (int) $args['recurrence_count'] : 1;
        $this->recurrence_end     = ! empty( $args['recurrence_end'] ) ? $args['recurrence_end'] : '';
        $this->parent_event_id    = ! empty( $args['parent_event_id'] ) ? (int) $args['parent_event_id'] : 0;
        $this->is_recurring       = ! empty( $args['is_recurring'] ) ? (bool) $args['is_recurring'] : false;
        $this->status             = ! empty( $args['status'] ) ? $args['status'] : 'draft';
        $this->event_type         = ! empty( $args['event_type'] ) ? $args['event_type'] : 'one-on-one';
        $this->availability       = ! empty( $args['availability'] ) ? (array) $args['availability'] : [];
        $this->buffer_before      = isset( $args['buffer_before'] ) ? (int) $args['buffer_before'] : 0;
        $this->buffer_after       = isset( $args['buffer_after'] ) ? (int) $args['buffer_after'] : 0;
        $this->price              = ! empty( $args['price'] ) ? (float) $args['price'] : 0;
        $this->featured_image     = ! empty( $args['featured_image'] ) ? $args['featured_image'] : '';
        $this->styling            = ! empty( $args['styling'] ) ? (array) $args['styling'] : [];
    }

    /**
     * Get the event ID.
     *
     * @return int
     */
    public function get_id(): int {
        return $this->id;
    }

    /**
     * Get the event title.
     *
     * @return string
     */
    public function get_title(): string {
        return $this->title;
    }

    /**
     * Set the event title.
     *
     * @param string $title The event title.
     */
    public function set_title( string $title ): void {
        $this->title = $title;
    }

    /**
     * Get the event description.
     *
     * @return string
     */
    public function get_description(): string {
        return $this->description;
    }

    /**
     * Set the event description.
     *
     * @param string $description The event description.
     */
    public function set_description( string $description ): void {
        $this->description = $description;
    }

    /**
     * Get the event date.
     *
     * @return string
     */
    public function get_date(): string {
        return $this->date;
    }

    /**
     * Set the event date.
     *
     * @param string $date The event date.
     */
    public function set_date( string $date ): void {
        $this->date = $date;
    }

    /**
     * Get the event time.
     *
     * @return string
     */
    public function get_time(): string {
        return $this->time;
    }

    /**
     * Set the event time.
     *
     * @param string $time The event time.
     */
    public function set_time( string $time ): void {
        $this->time = $time;
    }

    /**
     * Get the event end date.
     *
     * @since PBOOKING_SINCE
     *
     * @return string
     */
    public function get_end_date(): string {
        return $this->end_date;
    }

    /**
     * Set the event end date.
     *
     * @since PBOOKING_SINCE
     *
     * @param string $end_date The event end date.
     */
    public function set_end_date( string $end_date ): void {
        $this->end_date = $end_date;
    }

    /**
     * Get the event end time.
     *
     * @since PBOOKING_SINCE
     *
     * @return string
     */
    public function get_end_time(): string {
        return $this->end_time;
    }

    /**
     * Set the event end time.
     *
     * @since PBOOKING_SINCE
     *
     * @param string $end_time The event end time.
     */
    public function set_end_time( string $end_time ): void {
        $this->end_time = $end_time;
    }

    /**
     * Get the event date in UTC.
     *
     * @return string
     */
    public function get_date_utc(): string {
        return $this->date_utc;
    }

    /**
     * Set the event date in UTC.
     *
     * @param string $date_utc The event date in UTC.
     */
    public function set_date_utc( string $date_utc ): void {
        $this->date_utc = $date_utc;
    }

    /**
     * Get the event time in UTC.
     *
     * @return string
     */
    public function get_time_utc(): string {
        return $this->time_utc;
    }

    /**
     * Set the event time in UTC.
     *
     * @param string $time_utc The event time in UTC.
     */
    public function set_time_utc( string $time_utc ): void {
        $this->time_utc = $time_utc;
    }

    /**
     * Get the event end date in UTC.
     *
     * @since PBOOKING_SINCE
     *
     * @return string
     */
    public function get_end_date_utc(): string {
        return $this->end_date_utc;
    }

    /**
     * Set the event end date in UTC.
     *
     * @since PBOOKING_SINCE
     *
     * @param string $end_date_utc The event end date in UTC.
     */
    public function set_end_date_utc( string $end_date_utc ): void {
        $this->end_date_utc = $end_date_utc;
    }

    /**
     * Get the event end time in UTC.
     *
     * @since PBOOKING_SINCE
     *
     * @return string
     */
    public function get_end_time_utc(): string {
        return $this->end_time_utc;
    }

    /**
     * Set the event end time in UTC.
     *
     * @since PBOOKING_SINCE
     *
     * @param string $end_time_utc The event end time in UTC.
     */
    public function set_end_time_utc( string $end_time_utc ): void {
        $this->end_time_utc = $end_time_utc;
    }

    /**
     * Get the event timezone.
     *
     * @return string
     */
    public function get_timezone(): string {
        return $this->timezone;
    }

    /**
     * Set the event timezone.
     *
     * @param string $timezone IANA timezone string.
     */
    public function set_timezone( string $timezone ): void {
        $this->timezone = $timezone;
    }

    /**
     * Get the event duration.
     *
     * @return int
     */
    public function get_duration(): int {
        return $this->duration;
    }

    /**
     * Set the event duration.
     *
     * @param int $duration The event duration.
     */
    public function set_duration( int $duration ): void {
        $this->duration = $duration;
    }

    /**
     * Get the event location.
     *
     * @return string
     */
    public function get_location(): string {
        return $this->location;
    }

    /**
     * Set the event location.
     *
     * @param string $location The event location.
     */
    public function set_location( string $location ): void {
        $this->location = $location;
    }

    /**
     * Get the maximum number of attendees.
     *
     * @return int
     */
    public function get_max_attendees(): int {
        return $this->max_attendees;
    }

    /**
     * Set the maximum number of attendees.
     *
     * @param int $max_attendees The maximum number of attendees.
     */
    public function set_max_attendees( int $max_attendees ): void {
        $this->max_attendees = $max_attendees;
    }

    /**
     * Get the booking cutoff time.
     *
     * @return int
     */
    public function get_booking_cutoff(): int {
        return $this->booking_cutoff;
    }

    /**
     * Set the booking cutoff time.
     *
     * @param int $booking_cutoff The booking cutoff time in hours.
     */
    public function set_booking_cutoff( int $booking_cutoff ): void {
        $this->booking_cutoff = $booking_cutoff;
    }

    /**
     * Get whether waitlist is allowed.
     *
     * @return bool
     */
    public function get_allow_waitlist(): bool {
        return $this->allow_waitlist;
    }

    /**
     * Set whether waitlist is allowed.
     *
     * @param bool $allow_waitlist Whether to allow waitlist.
     */
    public function set_allow_waitlist( bool $allow_waitlist ): void {
        $this->allow_waitlist = $allow_waitlist;
    }

    /**
     * Get the recurrence pattern.
     *
     * @return string
     */
    public function get_recurrence_pattern(): string {
        return $this->recurrence_pattern;
    }

    /**
     * Set the recurrence pattern.
     *
     * @param string $recurrence_pattern The recurrence pattern.
     */
    public function set_recurrence_pattern( string $recurrence_pattern ): void {
        $this->recurrence_pattern = $recurrence_pattern;
    }

    /**
     * Get the recurrence count.
     *
     * @return int
     */
    public function get_recurrence_count(): int {
        return $this->recurrence_count;
    }

    /**
     * Set the recurrence count.
     *
     * @param int $recurrence_count The recurrence count.
     */
    public function set_recurrence_count( int $recurrence_count ): void {
        $this->recurrence_count = $recurrence_count;
    }

    /**
     * Get the recurrence end date.
     *
     * @return string
     */
    public function get_recurrence_end(): string {
        return $this->recurrence_end;
    }

    /**
     * Set the recurrence end date.
     *
     * @param string $recurrence_end The recurrence end date.
     */
    public function set_recurrence_end( string $recurrence_end ): void {
        $this->recurrence_end = $recurrence_end;
    }

    /**
     * Get the parent event ID.
     *
     * @return int
     */
    public function get_parent_event_id(): int {
        return $this->parent_event_id;
    }

    /**
     * Set the parent event ID.
     *
     * @param int $parent_event_id The parent event ID.
     */
    public function set_parent_event_id( int $parent_event_id ): void {
        $this->parent_event_id = $parent_event_id;
    }

    /**
     * Get whether this is a recurring event.
     *
     * @return bool
     */
    public function get_is_recurring(): bool {
        return $this->is_recurring;
    }

    /**
     * Set whether this is a recurring event.
     *
     * @param bool $is_recurring Whether this is a recurring event.
     */
    public function set_is_recurring( bool $is_recurring ): void {
        $this->is_recurring = $is_recurring;
    }

    /**
     * Get the event status.
     *
     * @return string
     */
    public function get_status(): string {
        return $this->status;
    }

    /**
     * Set the event status.
     *
     * @param string $status The event status.
     */
    public function set_status( string $status ): void {
        $this->status = $status;
    }

    /**
     * Get the event type.
     *
     * @return string
     */
    public function get_event_type(): string {
        return $this->event_type;
    }

    /**
     * Set the event type.
     *
     * @param string $event_type The event type.
     */
    public function set_event_type( string $event_type ): void {
        $this->event_type = $event_type;
    }

    /**
     * Get the availability schedule.
     *
     * @since PBOOKING_SINCE
     *
     * @return array
     */
    public function get_availability(): array {
        return $this->availability;
    }

    /**
     * Set the availability schedule.
     *
     * @since PBOOKING_SINCE
     *
     * @param array $availability The availability schedule.
     */
    public function set_availability( array $availability ): void {
        $this->availability = $availability;
    }

    /**
     * Get the buffer time before the event.
     *
     * @return int
     */
    public function get_buffer_before(): int {
        return $this->buffer_before;
    }

    /**
     * Set the buffer time before the event.
     *
     * @param int $buffer_before Minutes blocked before the event start.
     *
     * @return void
     */
    public function set_buffer_before( int $buffer_before ): void {
        $this->buffer_before = (int) $buffer_before;
    }

    /**
     * Get the buffer time after the event.
     *
     * @return int
     */
    public function get_buffer_after(): int {
        return $this->buffer_after;
    }

    /**
     * Set the buffer time after the event.
     *
     * @param int $buffer_after Minutes blocked after the event end.
     *
     * @return void
     */
    public function set_buffer_after( int $buffer_after ): void {
        $this->buffer_after = (int) $buffer_after;
    }

    /**
     * Get the event price.
     *
     * @return float
     */
    public function get_price(): float {
        return $this->price;
    }

    /**
     * Set the event price.
     *
     * @param float $price The event price.
     */
    public function set_price( float $price ): void {
        $this->price = $price;
    }

    /**
     * Get the featured image.
     *
     * @return string|int
     */
    public function get_featured_image() {
        return $this->featured_image;
    }

    /**
     * Set the featured image.
     *
     * @param string|int $featured_image The featured image.
     */
    public function set_featured_image( $featured_image ): void {
        $this->featured_image = $featured_image;
    }

    /**
     * Get the per-event styling tokens.
     *
     * @since PBOOKING_SINCE
     *
     * @return array
     */
    public function get_styling(): array {
        return $this->styling;
    }

    /**
     * Set the per-event styling tokens.
     *
     * @since PBOOKING_SINCE
     *
     * @param array $styling The styling tokens.
     */
    public function set_styling( array $styling ): void {
        $this->styling = $styling;
    }



    /**
     * Get the formatted event date.
     *
     * @return string
     */
    public function get_formatted_date(): string {
        if ( empty( $this->date ) ) {
            return '';
        }

        try {
            $tz = new \DateTimeZone( $this->timezone ? $this->timezone : \wp_timezone_string() );
            $dt = new \DateTime( $this->date . ' ' . ( $this->time ? $this->time : '00:00' ), $tz );

            return \wp_date( \get_option( 'date_format' ), $dt->getTimestamp(), $tz );
        } catch ( \Exception $e ) {
            $date = new \DateTime( $this->date );
            return $date->format( 'F j, Y' );
        }
    }

    /**
     * Get the formatted event time.
     *
     * @return string
     */
    public function get_formatted_time(): string {
        if ( empty( $this->time ) ) {
            return '';
        }

        try {
            $tz = new \DateTimeZone( $this->timezone ? $this->timezone : \wp_timezone_string() );
            $dt = new \DateTime( $this->date . ' ' . $this->time, $tz );

            return \wp_date( \get_option( 'time_format' ), $dt->getTimestamp(), $tz );
        } catch ( \Exception $e ) {
            $time = new \DateTime( $this->time );
            return $time->format( 'g:i A' );
        }
    }

    /**
     * Convert event to array.
     *
     * @return array
     */
    public function to_array(): array {
        return [
            'id'                 => $this->id,
            'title'              => $this->title,
            'description'        => $this->description,
            'date'               => $this->date,
            'time'               => $this->time,
            'end_date'           => $this->end_date,
            'end_time'           => $this->end_time,
            'date_utc'           => $this->date_utc,
            'time_utc'           => $this->time_utc,
            'end_date_utc'       => $this->end_date_utc,
            'end_time_utc'       => $this->end_time_utc,
            'timezone'           => $this->timezone,
            'duration'           => $this->duration,
            'location'           => $this->location,
            'max_attendees'      => $this->max_attendees,
            'booking_cutoff'     => $this->booking_cutoff,
            'allow_waitlist'     => $this->allow_waitlist,
            'recurrence_pattern' => $this->recurrence_pattern,
            'recurrence_count'   => $this->recurrence_count,
            'recurrence_end'     => $this->recurrence_end,
            'parent_event_id'    => $this->parent_event_id,
            'is_recurring'       => $this->is_recurring,
            'status'             => $this->status,
            'event_type'         => $this->event_type,
            'availability'       => $this->availability,
            'buffer_before'      => $this->buffer_before,
            'buffer_after'       => $this->buffer_after,
            'price'              => $this->price,
            'featured_image'     => $this->featured_image,
            'styling'            => $this->styling,
        ];
    }
}
