<?php

namespace FluentBooking\App\Services\LandingPage;

use FluentBooking\App\App;
use FluentBooking\App\Hooks\Handlers\FrontEndHandler;
use FluentBooking\App\Models\Booking;
use FluentBooking\App\Models\Calendar;
use FluentBooking\App\Models\CalendarSlot;
use FluentBooking\App\Services\CalendarEventService;
use FluentBooking\App\Services\BookingFieldService;
use FluentBooking\App\Services\BookingService;
use FluentBooking\App\Services\Helper;
use FluentBooking\Framework\Support\Arr;
use FluentBooking\Framework\Support\Collection;

class LandingPageHandler
{
    public function boot()
    {
        if (defined('FLUENT_BOOKING_LANDING_SLUG')) {
            add_action('template_redirect', [$this, 'handleSlugDefinedPage'], 1);
        }

        if (isset($_GET['fluent-booking'])) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended
            add_action('init', [$this, 'handleUrlParamsPage'], 100);
        }
    }

    public function handleSlugDefinedPage()
    {
        global $wp;
        // remove starting / and end / from $uri
        $uri = trim($wp->request, '/');
        $urlParts = explode('/', $uri);

        if ($urlParts[0] != FLUENT_BOOKING_LANDING_SLUG || count($urlParts) < 2) {
            return;
        }

        $authorSlug = sanitize_text_field($urlParts[1]);

        if (isset($_GET['embedded'])) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended
            $this->handleEmbeddedStyle();
        }

        $this->routeView($authorSlug, Arr::get($urlParts, 2, null));
    }

    public function handleUrlParamsPage()
    {
        $route = isset($_GET['fluent-booking']) ? sanitize_text_field(wp_unslash($_GET['fluent-booking'])) : ''; // phpcs:ignore WordPress.Security.NonceVerification.Recommended

        if (isset($_GET['embedded'])) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended
            $this->handleEmbeddedStyle();
        }

        if ($route == 'booking') {
            $this->handleAfterBookingPage();
            return;
        }

        $request = $_REQUEST; // phpcs:ignore WordPress.Security.NonceVerification.Recommended

        if (empty($request['host'])) {
            do_action('fluent_booking/landing_page_route_' . $route, $request);
            return;
        }

        $authorSlug = sanitize_text_field($request['host']);

        $slotSlug = null;

        if (!empty($request['event'])) {
            $slotSlug = sanitize_text_field($request['event']);
        }

        $this->routeView($authorSlug, $slotSlug);
    }

    public function routeView($authorSlug, $slotSlug = null)
    {
        $calendar = Calendar::where('slug', $authorSlug)->first();

        if (!$calendar) {
            return;
        }

        $sharingSettings = LandingPageHelper::getSettings($calendar);

        if (Arr::get($sharingSettings, 'enabled') != 'yes') {
            return '';
        }

        if ($slotSlug) {
            $slot = CalendarSlot::where('calendar_id', $calendar->id)
                ->where('slug', $slotSlug)
                ->first();
            if (!$slot) {
                return;
            }
            $this->renderBookingView($calendar, $slot);
        }

        $this->renderHostView($calendar);
    }

    private function renderHostView($calendar)
    {
        global $wp;
        $settings = LandingPageHelper::getSettings($calendar, 'public');

        $activeEvents = CalendarSlot::where('calendar_id', $calendar->id)
            ->where('status', 'active');
            
        if ($settings['show_type'] != 'all') {
            $activeEvents = $activeEvents->whereIn('id', $settings['enabled_slots']);
        }

        $activeEvents = $activeEvents->get();

        $activeEvents = CalendarEventService::processEvents($calendar, $activeEvents);

        $metaDescription = Helper::excerpt($calendar->description);

        $calendar->description = wpautop($calendar->description);

        $authorProfile = $calendar->getAuthorProfile(true);

        $globalVars = (new FrontEndHandler())->getGlobalVars();

        $currentUrl = home_url($wp->request);

        $globalVars['is_landing_page'] = true;
        $globalVars['is_pretty_url'] = defined('FLUENT_BOOKING_LANDING_SLUG');
        $globalVars['base_url'] = rtrim($currentUrl, '/');

        $jsVars = [
            'fluentCalendarPublicVars' => $globalVars,
            'fcal_landing_page' => true
        ];

        $extraJsFiles = [];

        foreach ($activeEvents as $activeEvent) {
            $event = clone $activeEvent;
            $vars = (new FrontEndHandler())->getCalendarEventVars($calendar, $event);
            $extraJs = $this->getEventLandingExtraJsFiles($vars['form_fields'], $event);
            if ($extraJs) {
                $vars['lazy_js_files'] = $extraJs;
            }
            $jsVars['fcal_public_vars_' . $calendar->id . '_' . $activeEvent->id] = $vars;
            $activeEvent->locations = $activeEvent->defaultLocationHtml();
            do_action_ref_array('fluent_booking/landing_page_event', [&$activeEvent]);
        }

        $assetUrl = App::getInstance('url.assets');
        $data = [
            'calendar'    => $calendar,
            'events'      => $activeEvents,
            'author'      => $authorProfile,
            'title'       => $calendar->title .' - '.get_bloginfo('name'),
            'description' => $metaDescription,
            'url'         => home_url($wp->request),
            'embedded'    => isset($_GET['embedded']) ? true : false, // phpcs:ignore WordPress.Security.NonceVerification.Recommended
            'css_files'   => [
                App::getInstance('url.assets') . 'public/saas.css'
            ],
            'js_files'    => [
                'fluent-booking-public-js' => $assetUrl . 'public/js/app.js',
            ],
            'js_vars'     => $jsVars,
            'header_js_files' => [
                'fluent_booking_team_app-js' => $assetUrl. 'public/js/team_app.js'
            ]
        ];

        if ($extraJsFiles) {
            $extraJsFiles = array_unique($extraJsFiles);
            $data['js_files'] = array_merge($data['js_files'], $extraJsFiles);
        }

        $data = apply_filters('fluent_booking/host_view_page_vars', $data, $calendar, $activeEvents, $authorProfile);

        $app = App::getInstance();
        status_header(200);
        $app->view->render('landing.author_landing', $data);
        exit(200);
    }

    private function renderBookingView($calendar, $calendarEvent, $existingBooking = null, $isReschedule = false)
    {
        if (!$isReschedule) {
            $settings = LandingPageHelper::getSettings($calendar, 'public');
            if ($settings['show_type'] != 'all') {
                if (!in_array($calendarEvent->id, $settings['enabled_slots'])) {
                    return '';
                }
            }
        }

        global $wp;

        $calendarEvent->max_lookup_date = $calendarEvent->getMaxLookUpDate();
        $calendarEvent->min_lookup_date = $calendarEvent->getMinLookUpDate();

        if (!empty($_REQUEST['booking_id'])) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended
            $bookingHash = sanitize_text_field(wp_unslash($_REQUEST['booking_id'])); // phpcs:ignore WordPress.Security.NonceVerification.Recommended
            $booking = Booking::where('hash', $bookingHash)
                ->where('event_id', $calendarEvent->id)
                ->first();
            if ($booking) {
                $this->showBookingConfimationPage($booking, $calendarEvent);
            }
        }

        $authorProfile = $calendarEvent->getAuthorProfile(true);

        $calendarEvent->pre_selects = false;

        if (gmdate('m') != gmdate('m', strtotime($calendarEvent->min_lookup_date))) { // phpcs:ignore WordPress.DateTime.RestrictedFunctions.date_date
            $calendarEvent->pre_selects = [
                'month' => gmdate('m', strtotime($calendarEvent->min_lookup_date)), // phpcs:ignore WordPress.DateTime.RestrictedFunctions.date_date
                'year'  => gmdate('Y', strtotime($calendarEvent->min_lookup_date)) // phpcs:ignore WordPress.DateTime.RestrictedFunctions.date_date
            ];
        }

        $assetUrl = App::getInstance('url.assets');

        $eventVars = (new FrontEndHandler())->getCalendarEventVars($calendar, $calendarEvent);

        $isRtl = Helper::fluentbooking_is_rtl();

        $publicCss = $isRtl ? 'public/saas-rtl.css' : 'public/saas.css';

        $title = $calendarEvent->title . ' ' . __('with', 'fluent-booking') . ' ' . $authorProfile['name'];

        $title = apply_filters('fluent_booking/booking_confirmation_page_title', $title, $calendarEvent, $authorProfile);

        $data = [
            'calendar'       => $calendar,
            'calendar_event' => $calendarEvent,
            'author'         => $authorProfile,
            'title'          => $title,
            'description'    => substr(strip_shortcodes(wp_strip_all_tags(str_replace(PHP_EOL, ' ', $calendarEvent->description))), 0, 300) . '...',
            'url'            => home_url($wp->request),
            'embedded'       => isset($_GET['embedded']) ? true : false, // phpcs:ignore WordPress.Security.NonceVerification.Recommended
            'css_files'      => [
                $assetUrl . $publicCss
            ],
            'js_files'       => [
                'fluent-booking-public-js' => $assetUrl . 'public/js/app.js',
            ],
            'js_vars'        => [
                'fluentCalendarPublicVars'                                     => (new FrontEndHandler())->getGlobalVars(),
                'fcal_public_vars_' . $calendar->id . '_' . $calendarEvent->id => $eventVars,
            ]
        ];

        $extraJs = $this->getEventLandingExtraJsFiles($eventVars['form_fields'], $calendarEvent);

        if ($extraJs) {
            $data['js_files'] = wp_parse_args($data['js_files'], $extraJs);
            add_action('fluent_booking/author_landing_head', function () use ($assetUrl) {
                ?>
                <style>
                    .fcal_phone_wrapper .flag {
                        background: url(<?php echo esc_url($assetUrl.'images/flags_responsive.png'); ?>) no-repeat;
                        background-size: 100%;
                    }
                </style>
                <?php
            });
        }

        $data = apply_filters('fluent_booking/event_landing_page_vars', $data, $calendar, $calendarEvent, $existingBooking);

        $app = App::getInstance();

        status_header(200);
        $app->view->render('landing.booking', $data);
        exit(200);
    }

    private function showBookingConfimationPage($booking, $actionType = 'confirmation')
    {
        $validActions = ['confirmation'];

        if (in_array($booking->status, ['scheduled', 'pending', 'rescheduled'])) {
            $validActions = array_merge($validActions, ['reschedule', 'cancel']);
        }

        if (!in_array($actionType, $validActions)) {
            $actionType = 'confirmation';
        }

        if ($actionType == 'reschedule') {
            $this->handleRescheduleView($booking);
        }

        if ($actionType == 'confirmation' && !empty($_REQUEST['ics']) && $_REQUEST['ics'] == 'download') { // phpcs:ignore WordPress.Security.NonceVerification.Recommended
            $icsText = BookingService::generateBookingICS($booking);
            // Output the ICS text
            header('Content-Type: text/calendar; charset=utf-8');
            header('Content-Disposition: attachment; filename=event.ics');
            echo $icsText; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
            die();
        }

        global $wp;

        $calendarEvent = $booking->calendar_event;

        $responseHtml = BookingService::getBookingConfirmationHtml($booking, $actionType);

        $authorProfile = $calendarEvent->getAuthorProfile(true);

        $publicCss = 'public/saas_public.css';
        if (Helper::fluentbooking_is_rtl()) {
            $publicCss = 'public/saas_public-rtl.css';
        }

        $data = [
            'title'       => __('Confirmation: ', 'fluent-booking') . $calendarEvent->title . ' ' . __('with', 'fluent-booking') . ' ' . $authorProfile['name'],
            'body'        => $responseHtml,
            'description' => substr(strip_shortcodes(wp_strip_all_tags(str_replace(PHP_EOL, ' ', $calendarEvent->description))), 0, 300) . '...',
            'css_files'   => [
                App::getInstance('url.assets') . $publicCss
            ],
            'js_files'    => [],
            'js_vars'     => [],
            'author'      => $authorProfile,
            'slot'        => $calendarEvent,
            'url'         => home_url($wp->request),
            'action_type' => $actionType,
            'embedded'    => isset($_GET['embedded']) ? true : false, // phpcs:ignore WordPress.Security.NonceVerification.Recommended
            'theme'       => Arr::get(get_option('_fluent_booking_settings'), 'theme','system-default'),
            'back_button' => [
                'show' => true,
                'text' => __('Back to home', 'fluent-booking'),
                'url'  => site_url('/')
            ]
        ];

        if ($actionType == 'cancel') {
            $data['js_files']['fluent-booking-public-manage-meeting-js'] = App::getInstance('url.assets') . 'public/js/public-manage-meeting.js';
        }

        $data = apply_filters('fluent_booking/booking_confirmation_page_vars', $data, $booking, $calendarEvent);

        $app = App::getInstance();
        status_header(200);
        $app->view->render('landing.confirmation_page', $data);
        exit(200);
    }

    private function handleAfterBookingPage()
    {
        $bookingHash = sanitize_text_field(wp_unslash(Arr::get($_REQUEST, 'meeting_hash'))); // phpcs:ignore WordPress.Security.NonceVerification.Recommended
        if (!$bookingHash) {
            return;
        }

        $booking = Booking::where('hash', $bookingHash)->first();
        if (!$booking) {
            return;
        }

        $type = Arr::get($_REQUEST, 'type', 'confirmation'); // phpcs:ignore WordPress.Security.NonceVerification.Recommended

        $this->showBookingConfimationPage($booking, $type);
    }

    private function handleRescheduleView(Booking $booking)
    {
        add_filter('fluent_booking/public_event_vars', function ($eventVars) use ($booking) {
            $onlyFields = ['name', 'email', 'rescheduling_reason'];

            $formFields = $eventVars['form_fields'];

            $formFields = Collection::make($formFields)->filter(function ($field) use ($onlyFields) {
                return in_array($field['name'], $onlyFields);
            })->map(function ($item) {
                $item['disabled'] = $item['name'] == 'rescheduling_reason' ? false : true;
                return $item;
            })->toArray();

            $formFields[] = [
                'type'    => 'hidden',
                'name'    => 'rescheduling_hash',
                'enabled' => true
            ];

            $eventVars['rescheduling'] = 'yes';
            $eventVars['form_fields'] = array_values($formFields);
            unset($eventVars['payment_items']);
            unset($eventVars['payment_methods']);

            return $eventVars;
        }, 10, 1);

        add_filter('fluent_calendar/global_booking_vars', function ($vars) use ($booking) {
            $vars['current_person'] = [
                'name'              => trim($booking->first_name . ' ' . $booking->last_name),
                'email'             => $booking->email,
                'rescheduling_hash' => $booking->hash
            ];

            return $vars;
        }, 10, 1);

        add_filter('fluent_booking/public_event_vars', function ($vars, $calendarEvent) {
            $vars['i18']['Schedule_Meeting'] = __('Confirm Reschedule', 'fluent-booking');
            $vars['i18']['Continue_to_Payments'] = __('Confirm Reschedule', 'fluent-booking');
            $vars['i18']['Confirm_Payment'] = __('Confirm Reschedule', 'fluent-booking');
            return $vars;
        }, 10, 2);

        add_action('fluent_booking/before_calendar_event_landing_page', function ($calendarEvent) use ($booking) {
            ?>
            <div class="fcal_rescheduling_wrap">
                <h3> <?php esc_html_e('You are rescheduling the booking: ', 'fluent-booking');
                    echo wp_kses_post($booking->getFullBookingDateTimeText($booking->person_time_zone, true)); ?>
                    (<?php echo esc_html($booking->person_time_zone); ?>) </h3>
            </div>
            <?php
        }, 10, 1);

        add_action('fluent_booking/author_landing_head', function () {
            ?>
            <style>
                .fluent_booking_app {
                    margin-top: 0 !important;
                    padding-top: 0 !important;
                }
            </style>
            <?php
        });

        $this->renderBookingView($booking->calendar, $booking->calendar_event, $booking, true);
    }

    private function handleEmbeddedStyle()
    {
        add_action('wp_print_styles', function () {
            global $wp_styles;
            if($wp_styles) {
                foreach ($wp_styles->queue as $style) {
                    $src = $wp_styles->registered[$style]->src;
                    if (
                        (strpos($src, 'fluentbooking') === false) &&
                        (strpos($src, 'fluent_booking') === false)
                    ) {
                        wp_dequeue_style($wp_styles->registered[$style]->handle);
                    }
                }
            }
        }, 100);
    }

    public function getEventLandingExtraJsFiles($formFields, $calendarEvent)
    {
        $files = [];
        $assetUrl = App::getInstance('url.assets');

        if (BookingFieldService::hasPhoneNumberField($formFields)) {
            $files['fluent-booking-phone-field-js'] = $assetUrl . 'public/js/phone-field.js';
        }

        if ($calendarEvent->type == 'paid') {
            $files['fluent-booking-checkout-sdk-stripe-js'] = 'https://js.stripe.com/v3/';
            $files['fluent-booking-checkout-handler-stripe-js'] = $assetUrl . 'public/js/stripe-checkout.js';
        }

        return $files;
    }
}
