<?php

namespace EasyLinkAutomations\Triggers\WooCommerce;

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

use EasyLinkAutomations\Triggers\BaseTrigger;

/**
 * Trigger that fires when a user purchases a WooCommerce product.
 */
final class ProductPurchasedTrigger extends BaseTrigger
{
    public static function getSlug(): string
    {
        return 'woocommerce/product_purchased';
    }

    public static function getName(): string
    {
        return __('User purchases a product', 'easylink-automations');
    }

    public static function getDescription(): string
    {
        return __('Triggers when a customer purchases a product (fires on processing for physical products, or on order completion for virtual/downloadable)', 'easylink-automations');
    }

    public static function getCategory(): string
    {
        return 'WooCommerce';
    }

    public static function getIcon(): string
    {
        return 'woocommerce';
    }


    public static function isAvailable(): bool
    {
        return class_exists('WooCommerce');
    }

    public static function getOutputFields(): array
    {
        return [
            'order_id'             => ['label' => 'Order ID', 'type' => 'number'],
            'order_number'         => ['label' => 'Order Number', 'type' => 'string'],
            'order_status'         => ['label' => 'Order Status', 'type' => 'string'],
            'order_total'          => ['label' => 'Order Total', 'type' => 'string'],
            'order_currency'       => ['label' => 'Order Currency', 'type' => 'string'],
            'order_date'           => ['label' => 'Order Date', 'type' => 'datetime'],
            'total_items_in_order' => ['label' => 'Total Items in Order', 'type' => 'number'],
            'billing_first_name'   => ['label' => 'Billing First Name', 'type' => 'string'],
            'billing_last_name'    => ['label' => 'Billing Last Name', 'type' => 'string'],
            'billing_email'        => ['label' => 'Billing Email', 'type' => 'email'],
            'billing_phone'        => ['label' => 'Billing Phone', 'type' => 'string'],
            'billing_city'         => ['label' => 'Billing City', 'type' => 'string'],
            'billing_country'      => ['label' => 'Billing Country', 'type' => 'string'],
            'product_id'           => ['label' => 'Product ID', 'type' => 'number'],
            'product_name'         => ['label' => 'Product Name', 'type' => 'string'],
            'product_sku'          => ['label' => 'Product SKU', 'type' => 'string'],
            'product_price'        => ['label' => 'Product Price', 'type' => 'string'],
            'product_url'          => ['label' => 'Product URL', 'type' => 'url'],
            'product_image'        => ['label' => 'Product Image URL', 'type' => 'url'],
            'product_category'     => ['label' => 'Product Category', 'type' => 'string'],
            'product_tag'          => ['label' => 'Product Tag', 'type' => 'string'],
            'is_downloadable'      => ['label' => 'Is Downloadable', 'type' => 'string'],
            'download_name'        => ['label' => 'Download Name', 'type' => 'string'],
            'download_link'        => ['label' => 'Download Link', 'type' => 'url'],
            'user_id'              => ['label' => 'Customer User ID', 'type' => 'number'],
            'user_login'           => ['label' => 'Customer Username', 'type' => 'string'],
            'user_email'           => ['label' => 'Customer Email', 'type' => 'email'],
            'display_name'         => ['label' => 'Customer Display Name', 'type' => 'string'],
            'first_name'           => ['label' => 'Customer First Name', 'type' => 'string'],
            'last_name'            => ['label' => 'Customer Last Name', 'type' => 'string'],
            'role'                 => ['label' => 'Customer Role', 'type' => 'string'],
        ];
    }

    public static function getConfigFields(): array
    {
        return [];
    }

    public function register(callable $callback): void
    {
        $this->callback = $callback;

        add_action('woocommerce_order_status_changed', function (int $orderId, string $fromStatus, string $toStatus, \WC_Order $order): void {
            if (!$order instanceof \WC_Order) {
                return;
            }

            $items = $order->get_items();
            $lastProduct = null;
            $productIds  = [];

            foreach ($items as $item) {
                $product       = wc_get_product($item->get_product_id());
                $lastProduct   = $product;
                $productIds[]  = $item->get_product_id();
            }

            $isVirtual      = $lastProduct ? $lastProduct->is_virtual() : false;
            $isDownloadable = $lastProduct ? $lastProduct->is_downloadable() : false;

            if ((!$isVirtual || !$isDownloadable) && 'processing' !== $toStatus) {
                return;
            }

            foreach ($productIds as $productId) {
                $data = $this->handle($orderId, $productId, count($productIds));
                $this->fire($data);
            }
        }, 10, 4);
    }

    public function handle(mixed ...$args): array
    {
        $orderId    = (int) $args[0];
        $productId  = (int) $args[1];
        $totalItems = (int) ($args[2] ?? 1);

        $order   = wc_get_order($orderId);
        $product = wc_get_product($productId);

        if (!$order instanceof \WC_Order || !$product) {
            return [];
        }

        $userId     = (int) $order->get_customer_id();
        $user       = $userId ? get_userdata($userId) : null;
        $roles      = $user->roles ?? [];
        $dateObj    = $order->get_date_created();
        $categories = implode(', ', wp_get_post_terms($productId, 'product_cat', ['fields' => 'names']));
        $tags       = implode(', ', wp_get_post_terms($productId, 'product_tag', ['fields' => 'names']));
        $imageUrl   = wp_get_attachment_image_url($product->get_image_id(), 'full') ?: '';

        $downloadName = '';
        $downloadLink = '';
        if ($product->is_downloadable()) {
            foreach ($product->get_downloads() as $download) {
                $downloadName = $download->get_name();
                $downloadLink = $download->get_file();
                break;
            }
        }

        return [
            'order_id'             => $orderId,
            'order_number'         => $order->get_order_number(),
            'order_status'         => $order->get_status(),
            'order_total'          => $order->get_total(),
            'order_currency'       => $order->get_currency(),
            'order_date'           => $dateObj ? $dateObj->format('Y-m-d H:i:s') : '',
            'total_items_in_order' => $totalItems,
            'billing_first_name'   => $order->get_billing_first_name(),
            'billing_last_name'    => $order->get_billing_last_name(),
            'billing_email'        => $order->get_billing_email(),
            'billing_phone'        => $order->get_billing_phone(),
            'billing_city'         => $order->get_billing_city(),
            'billing_country'      => $order->get_billing_country(),
            'product_id'           => $productId,
            'product_name'         => $product->get_name(),
            'product_sku'          => $product->get_sku(),
            'product_price'        => $product->get_price(),
            'product_url'          => get_permalink($productId),
            'product_image'        => $imageUrl,
            'product_category'     => $categories,
            'product_tag'          => $tags,
            'is_downloadable'      => $product->is_downloadable() ? 'yes' : 'no',
            'download_name'        => $downloadName,
            'download_link'        => $downloadLink,
            'user_id'              => $userId,
            'user_login'           => $user->user_login ?? '',
            'user_email'           => $user->user_email ?? $order->get_billing_email(),
            'display_name'         => $user->display_name ?? '',
            'first_name'           => $user->first_name ?? $order->get_billing_first_name(),
            'last_name'            => $user->last_name ?? $order->get_billing_last_name(),
            'role'                 => $roles[0] ?? '',
        ];
    }
}
