<?php

namespace FluentPlayer\App\Hooks\Handlers;
if (!defined('ABSPATH')) exit;

use FluentPlayer\App\App;
use FluentPlayer\App\Models\EmailCollection;
use FluentPlayer\App\Models\Media;
use FluentPlayer\App\Services\EmailCollectionService;
use FluentPlayer\App\Services\PresetService;
use FluentPlayer\App\Utils\Browser\Browser;
use FluentPlayer\Framework\Support\Arr;
use FluentPlayer\Framework\Support\Sanitizer;

class EmailCollectionHandler
{
    /**
     * @var \FluentPlayer\Framework\Foundation\Application
     */
    protected $app;

    /**
     * @var EmailCollectionService
     */
    protected $collectionService;

    /**
     * @var Browser
     */
    protected $browser;

    /**
     * EmailCollectionHandler constructor.
     */
    public function __construct()
    {
        $this->app = App::make();
        $this->browser = new Browser();
        $this->collectionService = new EmailCollectionService();
    }

    /**
     * Register AJAX hooks
     */
    public function handle()
    {
        // Register default AJAX handler
        add_action('wp_ajax_fluent_player_email_submit', [$this, 'submit']);
        add_action('wp_ajax_nopriv_fluent_player_email_submit', [$this, 'submit']);

        // Allow external code to register additional hooks
        do_action('fluent_player/email_collection_hooks', $this);
    }

    /**
     * Handle a new email submission from the frontend
     */
    public function submit()
    {
        try {
            // Get and validate data
            $data = $this->getRawRequestData();
            $this->validateRequestData($data);

            $type = Arr::get($data, 'type', 'preset');

            // Allow pre-processing or early termination
            $preProcessResult = apply_filters('fluent_player/pre_process_email_submit', null, $data);
            if ($preProcessResult !== null) {
                wp_send_json_success($preProcessResult);
                return;
            }

            if ('preset' == $type) {
                // Get preset data
                $presetData = PresetService::find(Arr::get($data, 'preset_slug'));
                if (!$presetData || !isset($presetData['settings'])) {
                    throw new \Exception(__('Invalid preset', 'fluent-player'));
                }
                $settings = $presetData['settings'];
            } elseif ('layer' == $type) {
                $mediaSettings = Media::getMediaSettings($data['media_id']);
                if (!$mediaSettings) {
                    throw new \Exception(__('Invalid layer', 'fluent-player'));
                }
                $layers = Arr::get($mediaSettings, 'layers', []);
                if (!$layers) {
                    throw new \Exception(__('Invalid layer', 'fluent-player'));
                }
                $layers = array_column($layers, null, 'id');
                $layer = Arr::get($layers, $data['layer_id'], []);
                if (!$layer) {
                    throw new \Exception(__('Invalid layer', 'fluent-player'));
                }
                $settings = $layer;
            } else {
                throw new \Exception(__('Invalid type', 'fluent-player'));
            }

            $existing = EmailCollection::where('email', $data['email'])
                ->when('preset' == $type, function ($query) use ($data) {
                    $query->where('preset_slug', Arr::get($data, 'preset_slug'))
                          ->where('media_id', Arr::get($data, 'media_id'));
                })
                ->when('layer' == $type, function ($query) use ($data) {
                    $query->where('layer_id', $data['layer_id']);
                })
                ->first();

            // Process providers
            $providers = Arr::get($settings, 'email_capture.providers', []);

            $providers = apply_filters('fluent_player/email_providers', $providers, $data, $settings);

            // Process email collection
            $integrationResults = $this->collectionService->processEmailCollection(
                $data['email'],
                $data,
                $providers
            );

            // Save or update email submission
            $created = false;

            if ($existing) {
                $submission = $existing;
                $existing->ip_address = Arr::get($data, 'ip_address');
                $existing->browser = Arr::get($data, 'browser');
                $existing->device = Arr::get($data, 'device');
                $existingMeta = $existing->meta ?: [];
                $existingMeta['provider_log'] = $integrationResults;
                $existing->meta = $existingMeta;
                $existing->updated_at = current_time('mysql');
                $existing->save();
            } else {
                // Prepare submission data
                $submissionData = [
                    'email'        => Arr::get($data, 'email'),
                    'media_id'     => Arr::get($data, 'media_id'),
                    'preset_slug'  => Arr::get($data, 'preset_slug'),
                    'layer_id'     => Arr::get($data, 'layer_id'),
                    'video_time'   => Arr::get($data, 'video_time'),
                    'user_id'      => Arr::get($data, 'user_id'),
                    'ip_address'   => Arr::get($data, 'ip_address'),
                    'browser'      => Arr::get($data, 'browser'),
                    'device'       => Arr::get($data, 'device'),
                    'meta'         => ['provider_log' => $integrationResults],
                    'created_at'   => current_time('mysql')
                ];

                // Allow modification of submission data
                $submissionData = apply_filters('fluent_player/submission_data', $submissionData, $data, $integrationResults);

                // Create new submission
                $submission = EmailCollection::create($submissionData);
                $created = true;
            }

            // Trigger action
            do_action('fluent_player/email_collected', $data, $submission, $created, $integrationResults);

            // Send response
            wp_send_json_success([
                'message' => __('Email collected successfully', 'fluent-player')
            ]);

        } catch (\Exception $e) {
            if (defined('WP_DEBUG') && WP_DEBUG) {
                // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_error_log -- Error logging for debugging
                error_log('Error processing email submission: ' . $e->getMessage());
            }

            wp_send_json_error([
                'message' => $e->getMessage()
            ], 500);
        }
    }

    /**
     * Get all request data
     *
     * @return array
     */
    protected function getRawRequestData()
    {
        $rawData = [
            'email'      => $this->app->request->get('email'),
            'media_id'   => $this->app->request->get('media_id'),
            'preset_slug' => $this->app->request->get('preset_slug'),
            'layer_id'   => $this->app->request->get('layer_id'),
            'type'       => $this->app->request->get('type', 'preset'),
            'video_time' => $this->app->request->get('video_time', 0),
            'nonce'      => $this->app->request->get('nonce'),
            'user_id'    => get_current_user_id() ?: null,
            'ip_address' => $this->app->request->getIp(),
            'browser'    => $this->browser->getBrowser(),
            'device'     => $this->browser->getPlatform(),
        ];

        $rawData = Sanitizer::sanitize($rawData, [
            'email'      => 'sanitizeEmail',
            'media_id'   => 'intval',
            'preset_slug' => 'sanitizeTextField',
            'layer_id'   => 'sanitizeTextField',
            'type'       => 'sanitizeTextField',
            'video_time' => 'floatval',
            'nonce'      => 'sanitizeTextField',
            'user_id'    => 'intval',
            'ip_address' => 'sanitizeTextField',
            'browser'    => 'sanitizeTextField',
            'device'     => 'sanitizeTextField',
        ]);

        // Allow modification of raw data
        return apply_filters('fluent_player/raw_request_data', $rawData);
    }

    /**
     * Validate request data
     *
     * @param array $data
     * @throws \Exception
     */
    protected function validateRequestData($data)
    {
        // Allow custom validation to run first
        $customValidation = apply_filters('fluent_player/validate_email_submission', null, $data);
        if ($customValidation instanceof \WP_Error) {
            throw new \Exception(\esc_html($customValidation->get_error_message()));
        }

        // Verify nonce
        if (!wp_verify_nonce($data['nonce'], 'fluent_player_frontend')) {
            throw new \Exception(\esc_html(__('Invalid request', 'fluent-player')));
        }

        // Validate email
        if (empty($data['email']) || !filter_var($data['email'], FILTER_VALIDATE_EMAIL)) {
            throw new \Exception(\esc_html(__('Invalid email address', 'fluent-player')));
        }

        // Validate preset slug
        if ('preset' == Arr::get($data, 'type') && empty($data['preset_slug'])) {
            throw new \Exception(\esc_html(__('Preset is required', 'fluent-player')));
        }

        // Validate layer ID
        if ('layer' == Arr::get($data, 'type') && empty($data['layer_id'])) {
            throw new \Exception(\esc_html(__('Layer ID is required', 'fluent-player')));
        }
    }
}
