<?php
namespace WalletUpPro\Core\Shortcodes;

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

use WalletUpPro\Core\PaymentRegistry;
use WalletUpPro\Core\Error\ErrorHandler;
use Exception;

class ShortcodeManager
{
    private static $instance = null;
    private $registry;
    private $errorHandler;
    private $displaySettings;

    /** @var array Shortcode examples */
    private const SHORTCODE_EXAMPLES = [
        'basic' => '[%s]',
        'qr' => '[%s amount="60" scan="yes" note="Payment for services"]',
        'button' => '[%s amount="60" scan="no" note="Service Fee"]',
        'link' => '[%s amount="60" scan="link" note="Event Ticket"]'
    ];

    public static function getInstance(): self
    {
        if (null === self::$instance) {
            self::$instance = new self();
        }
        return self::$instance;
    }

    private function __construct()
    {
        $this->registry = PaymentRegistry::getInstance();
        $this->errorHandler = ErrorHandler::getInstance();
        $this->loadSettings();
        $this->registerShortcodes();
        $this->addWidgetSupport();
    }

    private function loadSettings(): void
    {
        $this->displaySettings = get_option('wallet_up_display_settings', [
            'defaultMode' => 'qr',
            'qrSize' => 'medium',
            'qrColor' => '#674FBF',
            'qrBackground' => '#F4F4FF',
            'qrBorder' => true,
            'qrStyle' => 'rounded',
            'showDefaultMessage' => true,
            'customMessage' => '',
            'hideMessage' => false
        ]);
    }

    private function registerShortcodes(): void
    {
        try {
            // Register individual payment method shortcodes
            foreach ($this->registry->getAllMethods() as $methodId => $method) {
                add_shortcode($methodId, [$method, 'processShortcode']);
                $this->errorHandler->log("Registered shortcode for {$methodId}");
            }

            // Register generic payment shortcode
            add_shortcode('wallet_up', [$this, 'handleGenericShortcode']);

        } catch (Exception $e) {
            $this->errorHandler->log('Failed to register shortcodes: ' . $e->getMessage());
        }
    }

    private function addWidgetSupport(): void
    {
        add_filter('widget_text', 'shortcode_unautop');
        add_filter('widget_text', 'do_shortcode');
    }

    public function handleGenericShortcode($atts): string
    {
        try {
            $atts = $this->normalizeAttributes($atts);

            if (empty($atts['method'])) {
                throw new Exception(esc_html('Payment method must be specified for generic shortcode'));
            }

            $method = $this->registry->getMethod($atts['method']);
            if (!$method) {
                throw new Exception(esc_html(sprintf(
                    'Payment method %s not found or not enabled',
                    $atts['method']
                )));
            }

            // Remove method from attributes
            $methodId = $atts['method'];
            unset($atts['method']);

            // Format amount if present
            if (!empty($atts['amount'])) {
                $amount = preg_replace('/[^0-9.]/', '', $atts['amount']);
                if (function_exists('wc_price')) {
                    $atts['formatted_amount'] = html_entity_decode(wp_strip_all_tags(wc_price($amount)));
                } else {
                    $atts['formatted_amount'] = '$' . number_format((float) $amount, 2, '.', '');
                }
                $atts['amount'] = number_format((float) $amount, 2, '.', '');
            }

            // Apply display settings
            $atts = $this->applyDisplaySettings($atts);

            return $method->processShortcode($atts);

        } catch (Exception $e) {
            $this->errorHandler->log('Generic shortcode error: ' . $e->getMessage());
            return $this->formatError('Error processing payment shortcode.');
        }
    }

    /**
     * Preview shortcode output
     */
    public function previewShortcode($shortcode): string
    {
        try {
            if (!current_user_can('manage_options')) {
                throw new Exception(esc_html('Permission denied'));
            }

            // Parse shortcode tag
            if (!preg_match('/\[([^\s\]]+)/', $shortcode, $matches)) {
                throw new Exception(esc_html('Invalid shortcode format'));
            }

            $tag = $matches[1];
            $attributes = $this->parseShortcodeAttributes($shortcode);

            // Handle based on shortcode type
            if ($tag === 'wallet_up') {
                return $this->handleGenericShortcode($attributes);
            }

            $method = $this->registry->getMethod($tag);
            if (!$method) {
                throw new Exception(esc_html('Invalid payment method'));
            }

            // Apply display settings to preview
            $attributes = $this->applyDisplaySettings($attributes);

            return $method->processShortcode($attributes);

        } catch (Exception $e) {
            $this->errorHandler->log('Shortcode preview error: ' . $e->getMessage());
            return $this->formatError('Error previewing shortcode.');
        }
    }

    private function parseShortcodeAttributes(string $shortcode): array
    {
        $pattern = '/(\w+)=["\']([^"\']*)["\']|(\w+)=([^\s\]]*)/';
        $attributes = [];

        if (preg_match_all($pattern, $shortcode, $matches, PREG_SET_ORDER)) {
            foreach ($matches as $match) {
                if (!empty($match[1])) {
                    $attributes[$match[1]] = $match[2];
                } elseif (!empty($match[3])) {
                    $attributes[$match[3]] = $match[4];
                }
            }
        }

        return $this->normalizeAttributes($attributes);
    }

    private function applyDisplaySettings(array $atts): array
    {
        // Apply default mode if not specified
        if (empty($atts['scan'])) {
            $atts['scan'] = $this->displaySettings['defaultMode'] === 'qr' ? 'yes' : 'no';
        }

        // Format amount properly if set
        if (!empty($atts['amount'])) {
            // Remove any existing currency symbols and formatting
            $amount = preg_replace('/[^0-9.]/', '', $atts['amount']);
            // Format as decimal
            $atts['amount'] = number_format((float) $amount, 2, '.', '');
        }

        // Apply QR settings if in QR mode
        if ($atts['scan'] === 'yes') {
            $atts['size'] = $atts['size'] ?? $this->displaySettings['qrSize'];
            $atts['qr_color'] = $this->displaySettings['qrColor'];
            $atts['qr_background'] = $this->displaySettings['qrBackground'];
            $atts['qr_border'] = $this->displaySettings['qrBorder'];
            $atts['qr_style'] = $this->displaySettings['qrStyle'];
        }

        // Apply message settings with proper currency formatting
        $atts['show_message'] = !$this->displaySettings['hideMessage'];
        $atts['custom_message'] = $this->displaySettings['customMessage'];
        $atts['use_default_message'] = $this->displaySettings['showDefaultMessage'];

        // Add currency formatting settings (only if WooCommerce is active)
        if (function_exists('wc_get_price_decimals')) {
            $atts['currency_format'] = [
                'decimals' => wc_get_price_decimals(),
                'decimal_separator' => wc_get_price_decimal_separator(),
                'thousand_separator' => wc_get_price_thousand_separator(),
                'currency' => get_woocommerce_currency()
            ];
        } else {
            $atts['currency_format'] = [
                'decimals' => 2,
                'decimal_separator' => '.',
                'thousand_separator' => ',',
                'currency' => 'USD'
            ];
        }

        return $atts;
    }

    /**
     * Normalize shortcode attributes
     */
    private function normalizeAttributes($atts): array
    {
        if (!is_array($atts)) {
            $atts = [];
        }

        return shortcode_atts([
            'method' => '',
            'amount' => '',
            'note' => '',
            'scan' => '',
            'size' => '',
            'show_message' => true,
            'custom_message' => '',
            'use_default_message' => true
        ], $atts);
    }

    private function formatError(string $message): string
    {
        return sprintf(
            '<div class="walletup-error"><p>%s</p></div>',
            esc_html($message)
        );
    }

    public function getAvailableShortcodes(): array
    {
        $shortcodes = [];

        foreach ($this->registry->getAllMethods() as $methodId => $method) {
            $shortcodes[$methodId] = [
                'tag' => $methodId,
                'name' => ucfirst($methodId),
                'examples' => [
                    sprintf(self::SHORTCODE_EXAMPLES['basic'], $methodId),
                    sprintf(self::SHORTCODE_EXAMPLES['qr'], $methodId),
                    sprintf(self::SHORTCODE_EXAMPLES['button'], $methodId),
                    sprintf(self::SHORTCODE_EXAMPLES['link'], $methodId)
                ],
                'description' => $this->getShortcodeDescription($methodId)
            ];
        }

        // Add generic shortcode
        $shortcodes['wallet_up'] = [
            'tag' => 'wallet_up',
            'name' => 'Generic Payment',
            'examples' => [
                '[wallet_up method="venmo"]',
                '[wallet_up method="venmo" amount="60" scan="yes" note="Payment"]',
                '[wallet_up method="venmo" amount="60" scan="no"]',
                '[wallet_up method="venmo" amount="60" scan="link"]'
            ],
            'description' => 'Generic payment shortcode that supports all payment methods'
        ];

        return $shortcodes;
    }

    private function getShortcodeDescription(string $methodId): string
    {
        $descriptions = [
            'venmo' => 'Generate Venmo payment links and QR codes',
            'paypal' => 'Generate PayPal payment links and QR codes',
            'cashapp' => 'Generate Cash App payment links and QR codes',
            'zelle' => 'Generate Zelle payment links and QR codes'
        ];

        return $descriptions[$methodId] ?? 'Generate payment links and QR codes';
    }
}