<?php

namespace Licenzo\Modules\WooCommerce;

use Licenzo\Model\License;

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

class WooEmailService
{
    private const ALLOWED_EMAIL_IDS = [
        'customer_completed_order',
        'customer_processing_order',
    ];

    private const SEPARATOR_LENGTH = 40;

    public static function register(): void
    {
        add_action('woocommerce_email_after_order_table', [static::class, 'renderInEmail'], 10, 4);
        add_action('woocommerce_thankyou', [static::class, 'renderOnThankYou'], 20, 1);
    }

    /**
     * @param \WC_Order $order
     */
    public static function renderInEmail($order, bool $sentToAdmin = false, bool $plainText = false, $email = null): void
    {
        if ($sentToAdmin) {
            return;
        }

        if ($email && !in_array($email->id, static::ALLOWED_EMAIL_IDS, true)) {
            return;
        }

        $licenses = static::getLicensesForOrder($order);
        if (empty($licenses)) {
            return;
        }

        echo $plainText ? static::renderPlainText($licenses) : static::renderHtmlTable($licenses); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
    }

    public static function renderOnThankYou(int $orderId): void
    {
        if (!function_exists('wc_get_order') || $orderId <= 0) {
            return;
        }

        $order = wc_get_order($orderId);
        if (!$order) {
            return;
        }

        $licenses = static::getLicensesForOrder($order);
        if (empty($licenses)) {
            return;
        }

        echo static::renderHtmlTable($licenses); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
    }

    /**
     * @return License[]
     */
    private static function getLicensesForOrder($order): array
    {
        $subscriptionIds = static::extractSubscriptionIds($order);
        if (empty($subscriptionIds)) {
            return [];
        }

        return License::whereIn('subscription_id', $subscriptionIds)
            ->with('licenseProducts')
            ->get()
            ->all();
    }

    private static function extractSubscriptionIds($order): array
    {
        $ids = [];

        $single = (int) $order->get_meta('_licenzo_subscription_id', true);
        if ($single > 0) {
            $ids[] = $single;
        }

        $multi = $order->get_meta('_licenzo_subscription_ids', true);
        if (is_array($multi)) {
            foreach ($multi as $id) {
                $id = (int) $id;
                if ($id > 0) {
                    $ids[] = $id;
                }
            }
        }

        return array_values(array_unique($ids));
    }

    /**
     * @param License[] $licenses
     */
    private static function renderHtmlTable(array $licenses): string
    {
        $html = '<h2 style="margin-top:20px;">' . esc_html__('License Keys', 'licenzo') . '</h2>';
        $html .= '<table cellspacing="0" cellpadding="6" border="1" style="width:100%;border-collapse:collapse;margin-bottom:20px;">';
        $html .= '<thead><tr>';
        $html .= '<th style="text-align:left;">' . esc_html__('Product', 'licenzo') . '</th>';
        $html .= '<th style="text-align:left;">' . esc_html__('License Key', 'licenzo') . '</th>';
        $html .= '<th style="text-align:center;">' . esc_html__('Activations', 'licenzo') . '</th>';
        $html .= '<th style="text-align:left;">' . esc_html__('Expires', 'licenzo') . '</th>';
        $html .= '</tr></thead><tbody>';

        foreach ($licenses as $license) {
            $html .= static::renderHtmlRow($license);
        }

        $html .= '</tbody></table>';

        return $html;
    }

    private static function renderHtmlRow(License $license): string
    {
        $productName = static::resolveProductName($license);
        $activations = (int) $license->activation_count . '/' . (int) $license->activation_limit;
        $expires = static::formatExpireDate($license);

        $row = '<tr>';
        $row .= '<td>' . esc_html($productName) . '</td>';
        $row .= '<td><code>' . esc_html((string) $license->license_key) . '</code></td>';
        $row .= '<td style="text-align:center;">' . esc_html($activations) . '</td>';
        $row .= '<td>' . esc_html($expires) . '</td>';
        $row .= '</tr>';

        return $row;
    }

    /**
     * @param License[] $licenses
     */
    private static function renderPlainText(array $licenses): string
    {
        $output = "\n" . __('License Keys', 'licenzo') . "\n";
        $output .= str_repeat('-', static::SEPARATOR_LENGTH) . "\n\n";

        foreach ($licenses as $license) {
            $productName = static::resolveProductName($license);
            $activations = (int) $license->activation_count . '/' . (int) $license->activation_limit;
            $expires = static::formatExpireDate($license);

            $output .= __('Product', 'licenzo') . ': ' . $productName . "\n";
            $output .= __('License Key', 'licenzo') . ': ' . $license->license_key . "\n";
            $output .= __('Activations', 'licenzo') . ': ' . $activations . "\n";
            $output .= __('Expires', 'licenzo') . ': ' . $expires . "\n\n";
        }

        return $output;
    }

    private static function resolveProductName(License $license): string
    {
        $licenseProduct = $license->licenseProducts->first();
        if (!$licenseProduct) {
            return __('Unknown Product', 'licenzo');
        }

        $name = trim((string) ($licenseProduct->product_name ?? ''));
        $variationName = trim((string) ($licenseProduct->variation_name ?? ''));

        if ($variationName !== '' && $variationName !== $name) {
            $name .= ' — ' . $variationName;
        }

        return $name !== '' ? $name : __('Unknown Product', 'licenzo');
    }

    private static function formatExpireDate(License $license): string
    {
        if (!$license->expire_date) {
            return __('Never', 'licenzo');
        }

        return date_i18n(
            (string) get_option('date_format', 'Y-m-d'),
            strtotime((string) $license->expire_date)
        );
    }
}
