<?php
/**
 * Handles low stock notifications.
 *
 * @package StockGuardianPro
 */

declare(strict_types=1);

namespace StockGuardianPro\LowStock\Services;

use StockGuardianPro\LowStock\Plugin;
use WC_Product;
use StockGuardianPro\LowStock\Services\TelegramService;

\defined('ABSPATH') || exit;

final class NotificationService implements ServiceInterface
{
    private Plugin $plugin;

    public function __construct(Plugin $plugin)
    {
        $this->plugin = $plugin;
    }

    public function register(): void
    {
    }

    public function send_low_stock_email(WC_Product $product, int $stock, int $threshold): void
    {
        $recipients_option = get_option('woolsn_notifications_email', get_option('admin_email'));
        $recipients_string = $this->normalize_recipients($recipients_option);

        if ($recipients_string === '') {
            return;
        }

        $blog_name = wp_specialchars_decode(get_option('blogname'), ENT_QUOTES);
        $subject   = $this->build_subject($product, $stock, $threshold, $blog_name);

        $base_product_id = $product->is_type('variation') ? $product->get_parent_id() : $product->get_id();
        $variation_id    = $product->is_type('variation') ? $product->get_id() : 0;

        $email_data = $this->build_email_data($product, $stock, $threshold, $blog_name);

        $html_body = $this->render_template('emails/woolsn-low-stock-alert.php', $email_data);
        $plain_body = $this->render_template('emails/plain/woolsn-low-stock-alert.php', $email_data);

        $html_body = apply_filters(
            'woolsn_email_body_html',
            $html_body,
            $email_data,
            $product
        );

        $subject = apply_filters(
            'woolsn_email_subject',
            $subject,
            $product,
            $stock,
            $threshold
        );

        $html_body = apply_filters(
            'woolsn_email_message',
            $html_body,
            $product,
            $stock,
            $threshold
        );

        $sent = wp_mail(
            $recipients_string,
            $subject,
            $html_body,
            ['Content-Type: text/html; charset=UTF-8']
        );

        if (! $sent && $plain_body !== '') {
            $sent = wp_mail(
                $recipients_string,
                $subject,
                $plain_body,
                ['Content-Type: text/plain; charset=UTF-8']
            );
        }

        /** @var LoggerService|null $logger */
        $logger = $this->plugin->service(LoggerService::class);

        if ($sent) {
            $this->log_event($base_product_id, $variation_id, $product->get_name(), $stock, $threshold, 'email');

            if ($logger instanceof LoggerService) {
                $logger->info(
                    sprintf(
                        'Email sent for product #%1$d to %2$s (stock: %3$d, threshold: %4$d)',
                        $base_product_id,
                        $recipients_string,
                        $stock,
                        $threshold
                    )
                );
            }
        } elseif ($logger instanceof LoggerService) {
            $logger->error(
                sprintf(
                    'Email delivery failed for product #%1$d (stock: %2$d, threshold: %3$d)',
                    $base_product_id,
                    $stock,
                    $threshold
                )
            );
        }

        $this->maybe_notify_telegram($product, $stock, $threshold, $email_data, $base_product_id, $variation_id);

        do_action(
            'woolsn_notification_sent',
            [
                'product_id'   => $base_product_id,
                'variation_id' => $variation_id,
                'stock'        => $stock,
                'threshold'    => $threshold,
                'channel'      => 'email',
                'recipients'   => $recipients_string,
                'sent'         => $sent,
            ]
        );
    }

    /**
     * @return array<string, mixed>
     */
    private function build_email_data(WC_Product $product, int $stock, int $threshold, string $blog_name): array
    {
        $base_product_id = $product->is_type('variation') ? $product->get_parent_id() : $product->get_id();

        $email_heading = sprintf(
            /* translators: %s product name */
            __('Low stock for %s', 'stock-guardian-pro'),
            $product->get_name()
        );

        return [
            'email_heading'     => $email_heading,
            'product_name'      => $product->get_name(),
            'product_sku'       => $product->get_sku() ?: '',
            'product_admin_url' => $this->get_admin_product_url($base_product_id),
            'product_public_url'=> get_permalink($base_product_id) ?: '',
            'stock'             => $stock,
            'threshold'         => $threshold,
            'store_name'        => $blog_name,
            'generated_at'      => $this->format_datetime(),
            'email_intro'       => wp_kses_post((string) get_option('woolsn_email_intro', 'The stock level for the product below has reached or fallen below the configured threshold.')),
            'email_footer'      => wp_kses_post((string) get_option('woolsn_email_footer', 'If you need to adjust the stock threshold, open the product in WooCommerce and update the low stock settings.')),
        ];
    }

    private function get_admin_product_url(int $product_id): string
    {
        $url = get_edit_post_link($product_id, '');

        if (! $url) {
            $url = admin_url('post.php?post=' . $product_id . '&action=edit');
        }

        return $url;
    }

    private function render_template(string $template, array $data): string
    {
        $template_path = plugin_dir_path(WOOLSN_PLUGIN_FILE) . 'templates/';

        try {
            return wc_get_template_html(
                $template,
                $data,
                '',
                $template_path
            );
        } catch (\Throwable $throwable) { // phpcs:ignore Generic.CodeAnalysis.EmptyStatement.DetectedCatch
        }

        return '';
    }

    private function format_datetime(): string
    {
        return wp_date(
            get_option('date_format') . ' ' . get_option('time_format'),
            time()
        );
    }

    private function normalize_recipients($value): string
    {
        if (is_array($value)) {
            $emails = $value;
        } else {
            $emails = array_map('trim', explode(',', (string) $value));
        }

        $emails = array_filter(
            array_map('sanitize_email', $emails),
            static function ($email): bool {
                return ! empty($email);
            }
        );

        return implode(',', $emails);
    }

    private function build_subject(WC_Product $product, int $stock, int $threshold, string $blog_name): string
    {
        $template = (string) get_option('woolsn_email_subject_template', 'Stock Guardian Alert: {product_name}');

        $replacements = [
            '{site_name}'    => $blog_name,
            '{product_name}' => $product->get_name(),
            '{product_sku}'  => $product->get_sku() ?: '',
            '{stock}'        => (string) $stock,
            '{threshold}'    => (string) $threshold,
        ];

        $subject = strtr($template, $replacements);

        if ($subject === '') {
            $subject = sprintf(
                /* translators: %s product name */
                __('Stock Guardian alert: %s', 'stock-guardian-pro'),
                $product->get_name()
            );
        }

        return $subject;
    }

    private function log_event(
        int $product_id,
        int $variation_id,
        string $product_name,
        int $stock,
        int $threshold,
        string $channel
    ): void {
        /** @var EventRepository|null $events */
        $events = $this->plugin->service(EventRepository::class);

        if (! $events instanceof EventRepository) {
            return;
        }

        $events->log_event(
            $product_id,
            $variation_id,
            $product_name,
            $stock,
            $threshold,
            $channel
        );
    }

    private function maybe_notify_telegram(
        WC_Product $product,
        int $stock,
        int $threshold,
        array $email_data,
        int $base_product_id,
        int $variation_id
    ): void {
        /** @var TelegramService|null $telegram */
        $telegram = $this->plugin->service(TelegramService::class);
        /** @var LoggerService|null $logger */
        $logger = $this->plugin->service(LoggerService::class);

        if (! $telegram instanceof TelegramService || ! $telegram->is_enabled()) {
            return;
        }

        $payload = array_merge(
            $email_data,
            [
                'product_id'   => $base_product_id,
                'variation_id' => $variation_id,
            ]
        );

        $sent = $telegram->send_notification($payload);

        if ($sent) {
            $this->log_event(
                $base_product_id,
                $variation_id,
                $product->get_name(),
                $stock,
                $threshold,
                'telegram'
            );

            if ($logger instanceof LoggerService) {
                $logger->info(
                    sprintf(
                        'Telegram notification sent for product #%1$d (stock: %2$d, threshold: %3$d)',
                        $base_product_id,
                        $stock,
                        $threshold
                    )
                );
            }
        } elseif ($logger instanceof LoggerService) {
            $logger->warning(
                sprintf(
                    'Telegram notification failed for product #%1$d (stock: %2$d, threshold: %3$d)',
                    $base_product_id,
                    $stock,
                    $threshold
                )
            );
        }
    }
}

