<?php
/**
 * MeetingType Model
 *
 * Represents a meeting type definition (e.g. "30-min Intro Call", "1-hr Consultation").
 * Each employee can have multiple meeting types with their own availability schedule.
 *
 * @package RadiusTheme\RadiusBooking\Models
 * @since   1.2.0
 */

namespace RadiusTheme\RadiusBooking\Models;

if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

use RadiusTheme\RadiusBooking\Abstracts\BaseModel;

/**
 * Class MeetingType
 *
 * @property int    $id
 * @property int    $employee_id
 * @property string $name
 * @property string $description
 * @property string $slug
 * @property int    $duration
 * @property int    $buffer_before
 * @property int    $buffer_after
 * @property float  $price
 * @property string $color
 * @property string $location_type
 * @property string $location_details
 * @property bool   $is_active
 * @property bool   $requires_confirmation
 * @property int    $max_bookings_per_day
 * @property int    $min_notice_minutes
 * @property int    $max_advance_days
 * @property array  $settings
 */
class MeetingType extends BaseModel {

	/**
	 * The table associated with the model.
	 *
	 * @var string
	 */
	protected string $table = 'radius_booking_meeting_types';

	/**
	 * Whether soft deletes are enabled.
	 *
	 * @var bool
	 */
	protected bool $softDeletes = true;

	/**
	 * The attributes that are mass assignable.
	 *
	 * @var array
	 */
	protected array $fillable = array(
		'employee_id',
		'name',
		'description',
		'slug',
		'duration',
		'buffer_before',
		'buffer_after',
		'price',
		'color',
		'location_type',
		'location_details',
		'is_active',
		'requires_confirmation',
		'max_bookings_per_day',
		'min_notice_minutes',
		'max_advance_days',
		'settings',
		'picture_full_path',
		'picture_thumb_path',
	);

	/**
	 * The attributes that should be cast to specific types.
	 *
	 * @var array
	 */
	protected array $casts = array(
		'employee_id'           => 'integer',
		'duration'              => 'integer',
		'buffer_before'         => 'integer',
		'buffer_after'          => 'integer',
		'price'                 => 'float',
		'is_active'             => 'boolean',
		'requires_confirmation' => 'boolean',
		'max_bookings_per_day'  => 'integer',
		'min_notice_minutes'    => 'integer',
		'max_advance_days'      => 'integer',
		'settings'              => 'json',
	);

	/**
	 * Get the employee that owns this meeting type.
	 *
	 * @return \RadiusTheme\RadiusBooking\Core\ORM\Relations\BelongsTo
	 */
	public function employee() {
		return $this->belongsTo( User::class, 'employee_id' );
	}

	/**
	 * Get the availability windows for this meeting type.
	 *
	 * @return \RadiusTheme\RadiusBooking\Core\ORM\Relations\HasMany
	 */
	public function availability() {
		return $this->hasMany( MeetingTypeAvailability::class, 'meeting_type_id', 'id' );
	}

	/**
	 * Get the date overrides for this meeting type.
	 *
	 * @return \RadiusTheme\RadiusBooking\Core\ORM\Relations\HasMany
	 */
	public function dateOverrides() {
		return $this->hasMany( MeetingTypeDateOverride::class, 'meeting_type_id', 'id' );
	}

	/**
	 * Get all appointments booked for this meeting type.
	 *
	 * @return \RadiusTheme\RadiusBooking\Core\ORM\Relations\HasMany
	 */
	public function appointments() {
		return $this->hasMany( Appointment::class, 'meeting_type_id', 'id' );
	}

	/**
	 * Auto-generate a unique slug before creating.
	 *
	 * @return void
	 */
	protected function onCreating(): void {
		if ( empty( $this->slug ) ) {
			$this->slug = sanitize_title( $this->name ) . '-' . wp_generate_password( 6, false, false );
		}
	}

	/**
	 * Get the meeting type ID.
	 *
	 * @return int|null
	 */
	public function get_id() {
		return $this->attributes['id'] ?? null;
	}

	/**
	 * Get the meeting type name.
	 *
	 * @return string|null
	 */
	public function get_name() {
		return $this->attributes['name'] ?? null;
	}

	/**
	 * Get the meeting type slug.
	 *
	 * @return string|null
	 */
	public function get_slug() {
		return $this->attributes['slug'] ?? null;
	}

	/**
	 * Get the duration in minutes.
	 *
	 * @return int|null
	 */
	public function get_duration() {
		return $this->attributes['duration'] ?? null;
	}

	/**
	 * Get the price.
	 *
	 * @return float|null
	 */
	public function get_price() {
		return $this->attributes['price'] ?? null;
	}

	/**
	 * Get the employee ID.
	 *
	 * @return int|null
	 */
	public function get_employee_id() {
		return $this->attributes['employee_id'] ?? null;
	}

	/**
	 * Override setAttribute to use wp_json_encode for JSON fields
	 * instead of maybe_serialize, ensuring reliable DB storage.
	 *
	 * @param string $key   The attribute key.
	 * @param mixed  $value The value.
	 *
	 * @return void
	 */
	protected function setAttribute( string $key, $value ): void {
		if ( 'settings' === $key && ( is_array( $value ) || is_object( $value ) ) ) {
			$value = wp_json_encode( $value );
		}
		$this->attributes[ $key ] = $value;
	}

	/**
	 * Get the settings array.
	 *
	 * @return array
	 */
	public function get_settings() {
		$raw = $this->attributes['settings'] ?? null;

		if ( is_array( $raw ) ) {
			return $raw;
		}

		if ( is_string( $raw ) && ! empty( $raw ) ) {
			// Try JSON decode first.
			$decoded = json_decode( $raw, true );
			if ( is_array( $decoded ) ) {
				return $decoded;
			}
			// Fall back to PHP unserialize.
			$unserialized = maybe_unserialize( $raw );
			if ( is_array( $unserialized ) ) {
				return $unserialized;
			}
		}

		return array();
	}

	/**
	 * Get the integration settings.
	 *
	 * @return array
	 */
	public function integrations() {
		$settings = $this->get_settings();
		return $settings['integrations'] ?? array();
	}

	/**
	 * Get the payment method settings.
	 *
	 * @return array
	 */
	public function payment_methods() {
		$settings = $this->get_settings();
		return $settings['paymentMethods'] ?? array();
	}
}
