<?php

namespace FluentCrm\App\Hooks\Handlers;

use FluentCrm\App\Models\EventTracker;
use FluentCrm\App\Services\Helper;
use FluentCrm\Framework\Support\Arr;

class EventTrackingHandler
{
    public function register()
    {
        add_filter('fluentcrm_ajax_options_event_tracking_keys', [$this, 'getEventTrackingKeyOptions'], 10, 1);
        add_action('fluentcrm_contacts_filter_event_tracking', [$this, 'applyEventTrackingFilter'], 10, 2);
        add_action('fluent_crm/track_event_activity', [$this, 'trackEventActivity'], 10, 2);

        add_filter('fluent_crm/subscriber_info_widgets', [$this, 'addSubscriberInfoWidgets'], 10, 2);
        add_filter('fluent_crm/subscriber_info_widget_event_tracking', [$this, 'addSubscriberInfoWidgets'], 10, 2);

        add_filter('fluentcrm_advanced_filter_options', [$this, 'addEventTrackingFilterOptions'], 10, 1);

        add_filter('fluent_crm/event_tracking_condition_groups', [$this, 'addEventTrackingConditionOptions'], 10, 1);

        add_filter('fluentcrm_automation_condition_groups', function ($groups) {
            if (!Helper::isExperimentalEnabled('event_tracking')) {
                return $groups;
            }

            $groups['event_tracking'] = [
                'label'    => __('Event Tracking', 'fluent-crm'),
                'value'    => 'event_tracking',
                'children' => $this->getConditionItems()
            ];

            return $groups;
        });
    }

    public function getEventTrackingKeyOptions($options = [])
    {
        $items = EventTracker::select(['event_key'])
            ->groupBy('event_key')
            ->orderBy('event_key', 'ASC')
            ->get();

        $formattedItems = [];

        foreach ($items as $item) {
            $formattedItems[] = [
                'id'    => $item->event_key,
                'title' => $item->event_key
            ];
        }

        return $formattedItems;
    }

    public function applyEventTrackingFilter($query, $filters)
    {
        if (!Helper::isExperimentalEnabled('event_tracking')) {
            // Fail closed: with event tracking switched off a saved "did event X" segment
            // must match nobody. Returning the query unchanged would silently turn it
            // into "all subscribers" for list views and campaign sends.
            $query->whereRaw('1 = 0');
            return $query;
        }

        foreach ($filters as $filter) {
            if (!array_key_exists('value', $filter) || $filter['value'] === '') {
                continue;
            }

            $relation = 'trackingEvents';

            $filterProp = $filter['property'];

            if ($filterProp == 'event_tracking_key') {
                $operator = $filter['operator'];
                $values = $filter['value'];
                if ($operator == 'not_in') {
                    $query->whereDoesntHave($relation, function ($q) use ($values) {
                        $q->whereIn('event_key', $values);
                    });
                } else {
                    $query->whereHas($relation, function ($q) use ($values) {
                        $q->whereIn('event_key', $values);
                    });
                }
                continue;
            }

            if ($filterProp == 'event_tracking_title') {
                $operator = $filter['operator'];

                if ($operator == '=') {
                    $query->whereHas($relation, function ($q) use ($filter) {
                        $q->where('title', $filter['value']);
                    });
                } else if ($operator == '!=') {
                    $query->whereDoesntHave($relation, function ($q) use ($filter) {
                        $q->where('title', $filter['value']);
                    });
                } else if ($operator == 'contains') {
                    $query->whereHas($relation, function ($q) use ($filter) {
                        global $wpdb;
                        $q->where('title', 'LIKE', '%' . $wpdb->esc_like($filter['value']) . '%');
                    });
                } else if ($operator == 'not_contains') {
                    $query->whereDoesntHave($relation, function ($q) use ($filter) {
                        global $wpdb;
                        $q->where('title', 'LIKE', '%' . $wpdb->esc_like($filter['value']) . '%');
                    });
                }
                continue;
            }

            if ($filterProp == 'event_tracking_value') {

                $eventKey = Arr::get($filter, 'extra_value');
                if (!$eventKey) {
                    continue;
                }

                $operator = $filter['operator'];

                if ($operator == '=') {
                    $query->whereHas($relation, function ($q) use ($filter, $eventKey) {
                        $q->where('value', $filter['value'])
                            ->where('event_key', $eventKey);
                    });
                } else if ($operator == '!=') {
                    $query->whereDoesntHave($relation, function ($q) use ($filter, $eventKey) {
                        $q->where('value', $filter['value'])
                            ->where('event_key', $eventKey);
                    });
                } else if (in_array($operator, ['<', '>'])) {

                    $query->whereHas($relation, function ($q) use ($filter, $eventKey, $operator) {
                        $q->where('value', $operator, (int)$filter['value'])
                            ->where('event_key', $eventKey);
                    });
                } else if ($operator == 'contains') {
                    $query->whereHas($relation, function ($q) use ($filter, $eventKey) {
                        global $wpdb;
                        $q->where('value', 'LIKE', '%' . $wpdb->esc_like($filter['value']) . '%')
                            ->where('event_key', $eventKey);
                    });
                } else if ($operator == 'not_contains') {
                    $query->whereDoesntHave($relation, function ($q) use ($filter, $eventKey) {
                        global $wpdb;
                        $q->where('value', 'LIKE', '%' . $wpdb->esc_like($filter['value']) . '%')
                            ->where('event_key', $eventKey);
                    });
                }
                continue;
            }

            if ($filterProp == 'event_tracking_key_count') {

                $eventKey = Arr::get($filter, 'extra_value');
                if (!$eventKey) {
                    continue;
                }

                $operator = $filter['operator'];

                if ($operator == '=') {
                    $query->whereHas($relation, function ($q) use ($filter, $eventKey) {
                        $q->where('counter', $filter['value'])
                            ->where('event_key', $eventKey);
                    });
                } else if ($operator == '!=') {
                    $query->whereDoesntHave($relation, function ($q) use ($filter, $eventKey) {
                        $q->where('counter', $filter['value'])
                            ->where('event_key', $eventKey);
                    });
                } else if (in_array($operator, ['<', '>'])) {

                    $query->whereHas($relation, function ($q) use ($filter, $eventKey, $operator) {
                        $q->where('counter', $operator, (int)$filter['value'])
                            ->where('event_key', $eventKey);
                    });
                }

                continue;
            }
        }

        return $query;
    }

    public function trackEventActivity($data, $repeatable = true)
    {
        return FluentCrmApi('event_tracker')->track($data, $repeatable);
    }

    public function addSubscriberInfoWidgets($widgets, $subscriber)
    {
        if (!Helper::isExperimentalEnabled('event_tracking')) {
            return $widgets;
        }

        $events = EventTracker::where('subscriber_id', $subscriber->id)
            ->orderBy('updated_at', 'DESC')
            ->paginate();

        if ($events->isEmpty()) {
            return $widgets;
        }

        $html = '<div class="fc_scrolled_lists"><ul class="fcrm_event_tracking_lists">';
        foreach ($events as $event) {
            $html .= '<li>';
            $html .= '<p class="fcrm_event_tracking_title">' . esc_html($event->title) . '</p>';
            if ($event->value) {
                $html .= '<p class="fcrm_event_tracking_value">' . wp_kses_post($event->value) . '</p>';
            }
            $html .= '<div class="fcrm_event_tracking_footer">';
            $html .= '<div class="fcrm_event_tracking_badge">' . esc_attr($event->event_key) . '<span class="fcrm_event_tracking_count">(' . esc_html($event->counter) . ')</span></div>';
            $html .= '<span class="fcrm_event_tracking_date">' . $event->updated_at . '</span>';
            $html .= '</div>';
            $html .= '</li>';
        }
        $html .= '</ul></div>';

        $widgets['event_tracking'] = [
            'title'          => __('Event Tracking', 'fluent-crm'),
            'content'        => $html,
            'has_pagination' => $events->total() > $events->perPage(),
            'total'          => $events->total(),
            'per_page'       => $events->perPage(),
            'current_page'   => $events->currentPage()
        ];

        return $widgets;
    }

    public function addEventTrackingFilterOptions($groups)
    {
        if (!Helper::isExperimentalEnabled('event_tracking')) {
            return $groups;
        }

        $groups['event_tracking'] = [
            'label'    => __('Event Tracking', 'fluent-crm'),
            'value'    => 'event_tracking',
            'children' => $this->getConditionItems()
        ];

        return $groups;
    }

    public function addEventTrackingConditionOptions($items)
    {
        if (!Helper::isExperimentalEnabled('event_tracking')) {
            return $items;
        }

        return [
            [
                'label'    => __('Event Tracking', 'fluent-crm'),
                'value'    => 'event_tracking',
                'children' => $this->getConditionItems()
            ],
            [
                'label'    => __('Contact Segment', 'fluent-crm'),
                'value'    => 'segment',
                'children' => [
                    [
                        'label'             => __('Type', 'fluent-crm'),
                        'value'             => 'contact_type',
                        'type'              => 'selections',
                        'component'         => 'options_selector',
                        'option_key'        => 'contact_types',
                        'is_multiple'       => false,
                        'is_singular_value' => true
                    ],
                    [
                        'label'       => __('Tags', 'fluent-crm'),
                        'value'       => 'tags',
                        'type'        => 'selections',
                        'component'   => 'options_selector',
                        'option_key'  => 'tags',
                        'is_multiple' => true,
                    ],
                    [
                        'label'       => __('Lists', 'fluent-crm'),
                        'value'       => 'lists',
                        'type'        => 'selections',
                        'component'   => 'options_selector',
                        'option_key'  => 'lists',
                        'is_multiple' => true,
                    ]
                ],
            ]
        ];
    }

    private function getConditionItems()
    {
        return [
            [
                'label'              => __('Event Key', 'fluent-crm'),
                'value'              => 'event_tracking_key',
                'type'               => 'selections',
                'component'          => 'ajax_selector',
                'option_key'         => 'event_tracking_keys',
                'is_multiple'        => true,
                'custom_operators'   => [
                    'in'     => 'in',
                    'not_in' => 'not in'
                ],
                'creatable'          => true,
                'experimental_cache' => true,
                'help'               => __('Match one or more tracking events for your contacts.', 'fluent-crm')
            ],
            [
                'label'            => __('Event Occurrence Count', 'fluent-crm'),
                'value'            => 'event_tracking_key_count',
                'type'             => 'composite_optioned_compare',
                'help'             => __('The provided value for your selected event will be matched with the event occurrence count', 'fluent-crm'),
                'ajax_selector'    => [
                    'label'              => __('For Event Key', 'fluent-crm'),
                    'option_key'         => 'event_tracking_keys',
                    'experimental_cache' => true,
                    'is_multiple'        => false,
                    'placeholder'        => __('Select Event Key', 'fluent-crm')
                ],
                'value_config'     => [
                    'label'       => __('Event Count', 'fluent-crm'),
                    'type'        => 'input_text',
                    'data_type'   => 'number',
                    'placeholder' => __('Event Value', 'fluent-crm')
                ],
                'custom_operators' => [
                    '='  => 'equal',
                    '!=' => 'not equal',
                    '>'  => 'greater than',
                    '<'  => 'less than'
                ],
            ],
            [
                'label'            => __('Event Value', 'fluent-crm'),
                'value'            => 'event_tracking_value',
                'type'             => 'composite_optioned_compare',
                'help'             => __('The compare value will be matched with selected event & last recorded value of the selected event key', 'fluent-crm'),
                'ajax_selector'    => [
                    'label'              => __('For Event Key', 'fluent-crm'),
                    'option_key'         => 'event_tracking_keys',
                    'experimental_cache' => true,
                    'is_multiple'        => false,
                    'placeholder'        => __('Select Event Key', 'fluent-crm')
                ],
                'value_config'     => [
                    'label'       => __('Compare Value', 'fluent-crm'),
                    'type'        => 'input_text',
                    'placeholder' => __('Event Value', 'fluent-crm'),
                    'data_type'   => 'number',
                ],
                'custom_operators' => [
                    '='            => 'equal',
                    '!='           => 'not equal',
                    'contains'     => 'includes',
                    'not_contains' => 'does not include',
                    '>'            => 'greater than',
                    '<'            => 'less than'
                ],
            ],
            [
                'label' => __('Event Title', 'fluent-crm'),
                'value' => 'event_tracking_title',
                'type'  => 'text',
                'help'  => __('Match by tracking event title', 'fluent-crm')
            ],
        ];
    }
}
