<?php

namespace SugarCalendarBookings\Integrations\Outlook\Admin;

use SugarCalendarBookings\Integrations\OAuthRelay\OAuthConnectionModel;
use SugarCalendarBookings\Integrations\Outlook\OutlookCalendarSettingsRepository;
use SugarCalendarBookings\Integrations\Outlook\OutlookOAuthConnection;
use SugarCalendarBookings\Integrations\Outlook\OutlookSmartTagPicker;
use SugarCalendarBookings\Support\Helpers\Helpers;
use SugarCalendarBookings\Support\Helpers\UI;

/**
 * Outlook integration settings UI renderer.
 *
 * Stateless collaborator owning every admin `render_*` chunk for the Outlook
 * settings page. Lite OutlookIntegration delegates to this class; Pro adds a
 * separate OutlookEmployeeConnectionsRenderer for the employee-specific UI.
 *
 * @since 1.5.0
 */
class OutlookSettingsRenderer {

	/**
	 * Per-connection calendar settings repository.
	 *
	 * @since 1.5.0
	 *
	 * @var OutlookCalendarSettingsRepository
	 */
	private OutlookCalendarSettingsRepository $settings_repository;

	/**
	 * Smart-tag picker / meeting templates.
	 *
	 * @since 1.5.0
	 *
	 * @var OutlookSmartTagPicker
	 */
	private OutlookSmartTagPicker $smart_tags;

	/**
	 * Constructor.
	 *
	 * @since 1.5.0
	 *
	 * @param OutlookCalendarSettingsRepository $settings_repository Calendar settings repository.
	 * @param OutlookSmartTagPicker             $smart_tags          Smart-tag picker / templates.
	 */
	public function __construct(
		OutlookCalendarSettingsRepository $settings_repository,
		OutlookSmartTagPicker $smart_tags
	) {

		$this->settings_repository = $settings_repository;
		$this->smart_tags          = $smart_tags;
	}

	/**
	 * Render the "Create appointments on" dropdown for a single connection.
	 *
	 * Surfaced above the "Your Accounts" block so the destination calendar
	 * is the first thing the user picks after enabling the integration.
	 *
	 * @since 1.5.0
	 *
	 * @param OAuthConnectionModel $connection Connection to render settings for.
	 */
	public function render_connection_write_calendar( OAuthConnectionModel $connection ): void {

		$view = $this->build_connection_calendar_view( $connection );

		?>
		<div class="sugar-calendar-bookings-setting-row">
			<span class="sugar-calendar-bookings-setting-label">
				<label>
					<?php esc_html_e( 'Create appointments on', 'sugar-calendar-bookings-scheduling-appointments-lite' ); ?>
				</label>
			</span>
			<div class="sugar-calendar-bookings-setting-field">
				<?php
				UI::select_input(
					[
						'id'          => 'outlook-write-calendar-' . (int) $connection->id,
						// Bare-mode helpers skip the global form envelope; pre-wrap
						// with bracket notation so PHP $_POST builds the nested
						// array that InputProcessor's `connections.*.*` rules expect.
						'name'        => 'sugar-calendar-bookings[connections][' . (int) $connection->id . '][write_calendar_id]',
						'options'     => $view['options'],
						'value'       => $view['write_default'],
						'choicejs'    => true,
						'description' => esc_html__( 'Select the calendar on which new appointments will be added.', 'sugar-calendar-bookings-scheduling-appointments-lite' ),
					],
					true
				);
				?>
			</div>
		</div>
		<?php
	}

	/**
	 * Render the per-connection account extras panel.
	 *
	 * Today this renders only the "Calendars to check for conflicts" multi-select.
	 *
	 * @since 1.5.0
	 *
	 * @param OAuthConnectionModel $connection Connection to render extras for.
	 */
	public function render_account_extras( OAuthConnectionModel $connection ): void {

		$this->render_connection_conflict_calendars( $connection );
	}

	/**
	 * Render the meeting title + agenda smart-tag inputs.
	 *
	 * @since 1.5.0
	 */
	public function render_meeting_inputs(): void {

		UI::text_input_with_smart_tags(
			[
				'id'          => 'outlook-meeting-title',
				'name'        => 'integrations.outlook.meeting_title',
				'value'       => $this->smart_tags->get_title_template(),
				'label'       => esc_html__( 'Meeting Title', 'sugar-calendar-bookings-scheduling-appointments-lite' ),
				'description' => esc_html__( 'Title used for synced calendar events. You can find available placeholders via the smart tags button.', 'sugar-calendar-bookings-scheduling-appointments-lite' ),
				'smart_tags'  => $this->smart_tags->get_options(),
			]
		);

		UI::textarea_with_smart_tags(
			[
				'id'          => 'outlook-meeting-agenda',
				'name'        => 'integrations.outlook.meeting_agenda',
				'value'       => $this->smart_tags->get_agenda_template(),
				'label'       => esc_html__( 'Meeting Agenda', 'sugar-calendar-bookings-scheduling-appointments-lite' ),
				'description' => esc_html__( 'Body of the synced calendar event. HTML is supported. You can find available placeholders via the smart tags button.', 'sugar-calendar-bookings-scheduling-appointments-lite' ),
				'rows'        => 8,
				'smart_tags'  => $this->smart_tags->get_options(),
			]
		);
	}

	/**
	 * Render the Lite upsell for Connected Employee Accounts.
	 *
	 * Pro replaces this with the actual employee connections list via a
	 * separate renderer (see Pro\Integrations\Outlook\Admin\OutlookEmployeeConnectionsRenderer).
	 *
	 * @since 1.5.0
	 */
	public function render_employee_connections_upsell(): void {

		$upgrade_url = Helpers::get_utm_url(
			'https://sugarcalendar.com/pricing/bookings',
			[
				'medium'  => 'integrations',
				'content' => 'Outlook Employee Connections',
			]
		);

		?>
		<div class="sugar-calendar-bookings-setting-row">
			<span class="sugar-calendar-bookings-setting-label">
				<label>
					<?php esc_html_e( 'Connected Employee Accounts', 'sugar-calendar-bookings-scheduling-appointments-lite' ); ?>
					<?php UI::pro_badge( true ); ?>
				</label>
			</span>
			<div class="sugar-calendar-bookings-setting-field">
				<div class="scb-employee-connections-education">
					<p class="scb-employee-connections-education__title">
						<?php esc_html_e( 'No Accounts Connected', 'sugar-calendar-bookings-scheduling-appointments-lite' ); ?>
					</p>
					<p class="scb-employee-connections-education__description">
						<?php
						printf(
							wp_kses( /* translators: %1$s - upgrade to Pro link. */
								__( '<a href="%1$s" target="_blank" rel="noopener noreferrer">Upgrade to Pro</a> to add and connect your employee accounts to Sugar Calendar Bookings', 'sugar-calendar-bookings-scheduling-appointments-lite' ),
								[
									'a' => [
										'href'   => [],
										'target' => [],
										'rel'    => [],
									],
								]
							),
							esc_url( $upgrade_url )
						);
						?>
					</p>
				</div>
			</div>
		</div>
		<?php
	}

	/**
	 * Render the Lite upsell for Monitor Employee Appointments.
	 *
	 * Pro replaces this with the actual radio + employee picker via a
	 * separate renderer.
	 *
	 * @since 1.5.0
	 */
	public function render_monitor_employee_appointments_upsell(): void {

		$upgrade_url = Helpers::get_utm_url(
			'https://sugarcalendar.com/pricing/bookings',
			[
				'medium'  => 'integrations',
				'content' => 'Outlook Monitor Employee Appointments',
			]
		);

		?>
		<div class="sugar-calendar-bookings-setting-row">
			<span class="sugar-calendar-bookings-setting-label">
				<label>
					<?php esc_html_e( 'Monitor Employee Appointments', 'sugar-calendar-bookings-scheduling-appointments-lite' ); ?>
					<?php UI::pro_badge( true ); ?>
				</label>
			</span>
			<div class="sugar-calendar-bookings-setting-field">
				<div class="scb-employee-connections-education">
					<p class="scb-employee-connections-education__description">
						<?php
						printf(
							wp_kses( /* translators: %1$s - upgrade to Pro link. */
								__( '<a href="%1$s" target="_blank" rel="noopener noreferrer">Upgrade to Pro</a> to mirror employee-owned appointments on a connected admin calendar.', 'sugar-calendar-bookings-scheduling-appointments-lite' ),
								[
									'a' => [
										'href'   => [],
										'target' => [],
										'rel'    => [],
									],
								]
							),
							esc_url( $upgrade_url )
						);
						?>
					</p>
				</div>
			</div>
		</div>
		<?php
	}

	/**
	 * Render the "Calendars to check for conflicts" multi-select for a connection.
	 *
	 * Rendered inside the connection's account card as a gray-background panel.
	 *
	 * @since 1.5.0
	 *
	 * @param OAuthConnectionModel $connection Connection to render settings for.
	 */
	private function render_connection_conflict_calendars( OAuthConnectionModel $connection ): void {

		$view = $this->build_connection_calendar_view( $connection );

		?>
		<div class="scb-integration-accounts__item-extras">
			<label class="scb-integration-accounts__item-extras-label" for="outlook-conflict-calendars-<?php echo (int) $connection->id; ?>">
				<?php esc_html_e( 'Calendars to check for conflicts', 'sugar-calendar-bookings-scheduling-appointments-lite' ); ?>
				<span class="scb-integration-accounts__item-extras-hint">
					<?php esc_html_e( '(optional)', 'sugar-calendar-bookings-scheduling-appointments-lite' ); ?>
				</span>
			</label>
			<?php
			UI::select_input(
				[
					'id'       => 'outlook-conflict-calendars-' . (int) $connection->id,
					// Bracket notation (with trailing `[]` for the multi-select)
					// so PHP $_POST collects every choice into an array under
					// $_POST['sugar-calendar-bookings']['connections'][$id]['conflict_calendar_ids'].
					'name'     => 'sugar-calendar-bookings[connections][' . (int) $connection->id . '][conflict_calendar_ids][]',
					'options'  => $view['multi_options'],
					'value'    => $view['conflict_values'],
					'choicejs' => true,
					'multiple' => true,
					'data'     => [
						'placeholder' => esc_html__( 'Select calendars or keep empty to skip checks', 'sugar-calendar-bookings-scheduling-appointments-lite' ),
					],
				],
				true
			);
			?>
		</div>
		<?php
	}

	/**
	 * Build the option lists and currently-selected values for a connection.
	 *
	 * Centralizes the calendar lookup so the write and conflict rows can be
	 * rendered independently without duplicating the API/normalization logic.
	 *
	 * @since 1.5.0
	 *
	 * @param OAuthConnectionModel $connection Connection to inspect.
	 *
	 * @return array{
	 *     options: array<string, string>,
	 *     multi_options: array<string, string>,
	 *     write_default: string,
	 *     conflict_values: array<int, string>,
	 *     account_label: string
	 * }
	 */
	private function build_connection_calendar_view( OAuthConnectionModel $connection ): array {

		$settings        = $this->settings_repository->load( $connection );
		$calendars       = $this->settings_repository->list_calendars( $connection, new OutlookOAuthConnection( $connection ) );
		// The empty placeholder is rendered disabled so Choices.js still shows
		// "Select Calendar" as the prompt but does not offer it as a clickable
		// choice in the dropdown list. The `[ label, false ]` tuple maps to a
		// disabled <option> via UI::select_input().
		$options         = [
			'' => [ esc_html__( 'Select Calendar', 'sugar-calendar-bookings-scheduling-appointments-lite' ), false ],
		];
		$multi_options   = [];
		$write_default   = isset( $settings['write_calendar_id'] ) ? (string) $settings['write_calendar_id'] : '';
		$conflict_values = isset( $settings['conflict_calendar_ids'] ) && is_array( $settings['conflict_calendar_ids'] )
			? array_map( 'strval', $settings['conflict_calendar_ids'] )
			: [];

		$account_label = ! empty( $connection->account_email )
			? $connection->account_email
			: $connection->account_name;

		$default_calendar_id = '';

		foreach ( $calendars as $calendar ) {
			$cal_id   = isset( $calendar['id'] ) ? (string) $calendar['id'] : '';
			$cal_name = isset( $calendar['name'] ) ? (string) $calendar['name'] : $cal_id;

			if ( $cal_id === '' ) {
				continue;
			}

			$options[ $cal_id ]       = $account_label !== '' ? "{$cal_name} ({$account_label})" : $cal_name;
			$multi_options[ $cal_id ] = $cal_name;

			// Remember the account's primary calendar (Graph `isDefaultCalendar`)
			// so an unconfigured connection defaults to it below.
			if ( $default_calendar_id === '' && ! empty( $calendar['is_default'] ) ) {
				$default_calendar_id = $cal_id;
			}
		}

		// The write calendar is required, so it must never sit on the empty
		// placeholder when calendars exist. With no saved preference, default to
		// the account's primary calendar, falling back to the first available one
		// (Graph returns the default calendar first, so this stays sensible even
		// when the primary flag is unavailable).
		if ( $write_default === '' ) {
			if ( $default_calendar_id !== '' ) {
				$write_default = $default_calendar_id;
			} elseif ( ! empty( $multi_options ) ) {
				$write_default = (string) array_key_first( $multi_options );
			}
		}

		return [
			'options'         => $options,
			'multi_options'   => $multi_options,
			'write_default'   => $write_default,
			'conflict_values' => $conflict_values,
			'account_label'   => $account_label,
		];
	}
}
