<?php

namespace RTMCustomMails\MetaBox;

use DateTime;
use RTMCustomMails\Core;
use RTMCustomMails\Util;
use WordpressModels\Meta;
use WordpressModels\PostMetaBox;
use WP_Post;

class OrderEmailLogMetaBox extends PostMetaBox
{

    public function __construct()
    {
        parent::__construct('wrce-order-email-log',
            'Email Log',
            'shop_order',
            'side',
            'low',
            ['bootstrap-util'],
            Core::instance()->assets()
        );

        add_action('load-woocommerce_page_wc-orders', fn() => add_action('admin_enqueue_scripts', $this->enqueueScripts(...), 10, 1));
        add_action('add_meta_boxes', [$this, 'registerMetaBoxHPOS']);
    }

    public function registerMetaBoxHPOS()
    {
        if (get_current_screen()->id === 'woocommerce_page_wc-orders') {
            add_meta_box(
                $this->id,
                'Email Log',
                [$this, 'renderUsingOrder'],
                'woocommerce_page_wc-orders',
                'side',
                'low'
            );
        }
    }

    /**
     * Ensure that the date is displayed in the local timezone.
     *
     * @param string $dateString
     * @return DateTime
     */
    private function asLocalDateTime(string $dateString): DateTime
    {
        try {
            $dateTime = new DateTime($dateString);
            $dateTime->setTimezone(new \DateTimeZone(get_option('timezone_string')));
        } catch (\Exception $e) {
            // Fallback to epoch, indicating an error
            $dateTime = new DateTime('@0');
        }

        return $dateTime;
    }

    public function getEmailDateMeta(string $suffix, int $orderId): array
    {
        $metas = Meta::getAllMetaKeysAndValuesLike("_wrce_%_$suffix", '', $orderId);
        $sentEmails = [];
        foreach ($metas as [$key, $value]) {
            $value = maybe_unserialize($value);

            $emailId = substr($key, 6, strlen($key) - strlen($suffix) - 7);
            if (is_array($value)) {
                $sentEmails[$emailId] = array_merge($sentEmails[$emailId] ?? [], array_map([$this, 'asLocalDateTime'], $value));
            } else {
                $sentEmails[$emailId][] = $this->asLocalDateTime($value);
            }
        }
        return $sentEmails;
    }

    public function renderMetaBox(WP_Post $post): void
    {
        $id = $post->ID;
        $this->renderContent($id);
    }

    public function renderUsingOrder(\WC_Abstract_Order $order)
    {
        $this->renderContent($order->get_id());
    }

    /**
     * @param int $id
     * @return void
     */
    public function renderContent(int $id): void
    {
        $sentEmails = $this->getEmailDateMeta('sent', $id);
        $failedEmails = $this->getEmailDateMeta('send_failure', $id);

        if (!$sentEmails && !$failedEmails) {
            echo __("No logs found for this order", "wrce");
            return;
        }

        $emails = [];
        foreach ($sentEmails as $emailId => $dates) {
            $emails[$emailId] = array_map(fn($date) => [
                'color' => 'success',
                'type' => 'success',
                'date' => $date
            ], $dates);
        }
        foreach ($failedEmails as $emailId => $dates) {
            $emails[$emailId] = array_merge($emails[$emailId] ?? [], array_map(fn($date) => [
                'color' => 'danger',
                'type' => 'failure',
                'date' => $date
            ], $dates));
            usort($emails[$emailId], fn($d0, $d1) => $d0['date'] <=> $d1['date']);
        }

        foreach ($emails as $emailId => $dates) {
            $emailInstance = Util::getEmailById($emailId);
            if ($emailInstance) {
                $emailTitle = $emailInstance->get_title();
            } else {
                $emailTitle = $emailId;
            }
            echo "<div><strong>$emailTitle</strong><br/>";
            echo join(" ", array_map(fn(array $entry) => "<span class='badge text-bg-{$entry['color']}' title='{$entry['type']}'>{$entry['date']->format('Y-m-d H:i:s')}</span>", $dates));
            echo "</div>";
        }
    }

}