<?php

namespace FluentPlayer\App\Http\Controllers;

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

use FluentPlayer\App\Services\EmailProviderService;
use FluentPlayer\Framework\Http\Request\Request;
use FluentPlayer\Framework\Support\Arr;
use FluentPlayer\Framework\Support\Sanitizer;
use FluentPlayer\Framework\Validator\Validator;

class EmailProviderController extends Controller
{
    /**
     * Constructor
     */
    public function __construct()
    {
        // Ensure providers are initialized
        parent::__construct();
        EmailProviderService::init();
    }

    /**
     * Get all available email providers
     *
     * @param Request $request
     * @return \WP_REST_Response
     */
    public function getProvidersSettings(Request $request)
    {
        $providers = EmailProviderService::getProvidersSettings();
        $providersMetaData = EmailProviderService::getProvidersMetaData();

        $defaultAllowedTypes = [
            'application/pdf',
            'image',
            'video',
            'application/msword',
            'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
            'application/vnd.ms-excel',
            'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
        ];

        $allowedAttachmentTypes = apply_filters(
            'fluent_player/email_attachment_allowed_types',
            $defaultAllowedTypes
        );

        return $this->sendSuccess([
            'providers' => $providers,
            'providers_meta' => $providersMetaData,
            'allowed_attachment_types' => $allowedAttachmentTypes
        ]);
    }

    /**
     * Save provider settings
     *
     * @param Request $request
     * @return \WP_REST_Response
     */
    public function saveProviderSettings(Request $request)
    {
        $data = $request->all();
        // Validate sanitized data
        $validation = Validator::make($data, [
            'provider' => 'required|string',
            'settings' => 'required|array'
        ]);

        if ($validation->fails()) {
            return $this->sendError([
                'message' => __('Validation failed', 'fluent-player'),
                'errors'  => $validation->errors()
            ], 422);
        }

        $provider = $data['provider'];
        $settings = $data['settings'];

        $providerInstance = EmailProviderService::getProvider($provider);
        if (!$providerInstance) {
            return $this->sendError([
                'message' => __('Invalid provider', 'fluent-player')
            ], 422);
        }

        $result = EmailProviderService::saveProviderSettings($provider, $settings);

        if (is_wp_error($result)) {
            return $this->sendError([
                'message' => $result->get_error_message()
            ], 400);
        }

        return $this->sendSuccess([
            'message'  => __('Settings saved successfully', 'fluent-player'),
            'settings' => $result
        ]);
    }

    /**
     * Export emails from the database
     *
     * @param Request $request
     * @return \WP_REST_Response
     */
    public function exportEmails(Request $request)
    {
        try {
            // Validate request data
            $validation = Validator::make($request->all(), [
                'format' => 'nullable|string|in:csv,json,ods'
            ]);

            if ($validation->fails()) {
                return $this->sendError([
                    'message' => __('Validation failed', 'fluent-player'),
                    'errors'  => $validation->errors()
                ], 422);
            }

            // Get format from request, default to CSV
            $format = $request->get('format', 'csv');

            // Sanitize format
            $format = sanitize_text_field($format);

            // Call service to export emails
            $result = EmailProviderService::exportEmails($format);

            if (is_wp_error($result)) {
                return $this->sendError([
                    'message' => $result->get_error_message()
                ], 400);
            }

            // ODS is a binary ZIP file. Returning it as raw bytes through an AJAX response
            // corrupts it because JavaScript treats the response as a UTF-16 string and
            // replaces invalid byte sequences with U+FFFD. Return base64-encoded content
            // in JSON instead; the frontend decodes it into a Uint8Array before Blob creation.
            if (!empty($result['file_path'])) {
                $tmpFile = $result['file_path'];
                // phpcs:ignore WordPress.WP.AlternativeFunctions.file_get_contents_file_get_contents -- local temp file
                $raw = file_get_contents($tmpFile);
                @unlink($tmpFile);
                return $this->sendSuccess([
                    'filename'       => $result['filename'],
                    'content_base64' => base64_encode($raw),
                    'count'          => $result['count'] ?? 0,
                ]);
            }

            // CSV / JSON: plain text — safe to output directly
            $content = (string) ($result['content'] ?? '');

            while (ob_get_level()) {
                ob_end_clean();
            }

            header('Content-Type: ' . $result['mime_type']);
            header('Content-Disposition: attachment; filename="' . $result['filename'] . '"');
            header('Content-Length: ' . mb_strlen($content, '8bit'));
            header('Cache-Control: no-cache, no-store, must-revalidate');
            header('Pragma: no-cache');
            header('Expires: 0');

            // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- Pre-encoded CSV/JSON export content
            echo $content;
            exit;
        } catch (\Exception $e) {
            return $this->sendError(['message' => $e->getMessage()], 500);
        }
    }


    /**
     * Get provider-specific resources (lists, tags, etc.)
     *
     * @param string $provider Provider type
     * @param string $resource Resource type (lists, tags, etc.)
     * @return \WP_REST_Response
     */
    public function getProviderResource(Request $request, $provider, $resource)
    {
        $params = $request->get();
        array_walk_recursive($params, function (&$value) {
            if (is_string($value)) {
                $value = sanitize_text_field($value);
            }
        });

        $result = EmailProviderService::handleProviderAction($provider, $resource, $params);

        if (is_wp_error($result)) {
            return $this->sendError([
                'message' => $result->get_error_message()
            ], 422);
        }

        return $this->sendSuccess($result);
    }

    /**
     * Validate a provider field
     *
     * @param Request $request
     * @param string $provider
     * @param string $field
     * @return \WP_REST_Response
     */
    public function validateProviderField(Request $request, $provider, $field)
    {
        // Sanitize provider and field
        $provider = Sanitizer::sanitizeTextField($provider);
        $field = Sanitizer::sanitizeTextField($field);

        // Get field value from request
        $value = $request->get($field);
        if ($value === null) {
            return $this->sendError([
                'message' => __('Field value is required', 'fluent-player')
            ], 422);
        }

        $providerInstance = EmailProviderService::getProvider($provider);
        if (!$providerInstance) {
            return $this->sendError([
                'message' => __('Invalid provider', 'fluent-player')
            ], 422);
        }

        $result = $providerInstance->validateField($field, $value);

        if (is_wp_error($result)) {
            return $this->sendError([
                'message' => $result->get_error_message()
            ], 400);
        }

        return $this->sendSuccess($result);
    }
}
