<?php

namespace Calio\Admin;

use Calio\Support\ProAccess;
use Calio\Support\Settings;
use Calio\Support\WidgetCatalog;

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

/**
 * Adds a compact Calio status overview to the WordPress dashboard.
 */
final class DashboardWidget
{
    private const STYLE_HANDLE = 'calio-dashboard-widget';
    private const SCRIPT_HANDLE = 'calio-live-inventory-hud';
    private const INVENTORY_NONCE_ACTION = 'calio_live_inventory_hud';

    public function __construct()
    {
        add_action('wp_dashboard_setup', [$this, 'register']);
        add_action('admin_enqueue_scripts', [$this, 'enqueue_assets']);
        add_action('wp_ajax_calio_refresh_inventory_hud', [$this, 'ajax_refresh_inventory']);
    }

    /**
     * Registers the overview for administrators who can manage plugin settings.
     */
    public function register(): void
    {
        if (
            Settings::is_dashboard_widget_enabled('calio-overview')
            && current_user_can('manage_options')
        ) {
            wp_add_dashboard_widget(
                'calio_addon_dashboard_overview',
                esc_html__('Calio Addon Overview', 'calio-addon'),
                [$this, 'render']
            );
        }

        if (
            Settings::is_dashboard_widget_enabled('live-inventory-hud')
            && $this->can_view_inventory()
        ) {
            wp_add_dashboard_widget(
                'calio_live_inventory_hud',
                esc_html__('Live Inventory HUD', 'calio-addon'),
                [$this, 'render_inventory_hud'],
                null,
                null,
                'normal',
                'high'
            );
        }
    }

    /**
     * Loads dashboard-specific presentation only on the WordPress home screen.
     */
    public function enqueue_assets(string $hook_suffix): void
    {
        if ($hook_suffix !== 'index.php') {
            return;
        }

        $show_overview = Settings::is_dashboard_widget_enabled('calio-overview')
            && current_user_can('manage_options');
        $show_inventory = Settings::is_dashboard_widget_enabled('live-inventory-hud')
            && $this->can_view_inventory();

        if (!$show_overview && !$show_inventory) {
            return;
        }

        wp_enqueue_style(self::STYLE_HANDLE, CALIO_URL . 'assets/admin/dashboard-widget.css', [], CALIO_VERSION);

        if ($show_inventory) {
            wp_enqueue_script(
                self::SCRIPT_HANDLE,
                CALIO_URL . 'assets/admin/live-inventory-hud.js',
                [],
                CALIO_VERSION,
                true
            );
            wp_localize_script(
                self::SCRIPT_HANDLE,
                'calioInventoryHud',
                [
                    'ajaxUrl' => admin_url('admin-ajax.php'),
                    'nonce' => wp_create_nonce(self::INVENTORY_NONCE_ACTION),
                    'action' => 'calio_refresh_inventory_hud',
                    'fileName' => 'calio-inventory-' . wp_date('Y-m-d') . '.csv',
                    'labels' => [
                        'refreshing' => __('Refreshing inventory...', 'calio-addon'),
                        'refresh' => __('Refresh', 'calio-addon'),
                        'exportEmpty' => __('There are no visible inventory rows to export.', 'calio-addon'),
                        'requestFailed' => __('Inventory could not be refreshed. Please try again.', 'calio-addon'),
                        'notManaged' => __('Not managed', 'calio-addon'),
                        'notSet' => __('Not set', 'calio-addon'),
                        'productName' => __('Product Name', 'calio-addon'),
                        'sku' => __('SKU', 'calio-addon'),
                        'stockLevel' => __('Stock Level', 'calio-addon'),
                        'price' => __('Price', 'calio-addon'),
                    ],
                ]
            );
        }
    }

    public function render_inventory_hud(): void
    {
        if (!$this->can_view_inventory()) {
            return;
        }

        if (!function_exists('wc_get_products')) {
            echo '<div class="calio-inventory-hud__notice">';
            echo '<p>' . esc_html__('WooCommerce must be installed and active to monitor inventory.', 'calio-addon') . '</p>';
            echo '</div>';
            return;
        }

        $threshold = 5;
        $items = $this->inventory_items($threshold);
        $summary = $this->inventory_summary($items, $threshold);

        echo '<div class="calio-inventory-hud" data-calio-inventory-hud data-threshold="' . esc_attr((string) $threshold) . '">';
        echo '<div class="calio-inventory-hud__summary">';
        $this->render_inventory_stat((string) $summary['total'], esc_html__('Tracked items', 'calio-addon'), 'total');
        $this->render_inventory_stat((string) $summary['low'], esc_html__('Low stock', 'calio-addon'), 'low');
        $this->render_inventory_stat((string) $summary['out'], esc_html__('Out of stock', 'calio-addon'), 'out');
        echo '</div>';

        echo '<div class="calio-inventory-hud__controls">';
        echo '<label class="calio-inventory-hud__search">';
        echo '<span class="screen-reader-text">' . esc_html__('Search inventory by product name or SKU', 'calio-addon') . '</span>';
        echo '<input type="search" data-inventory-search placeholder="' . esc_attr__('Search product or SKU...', 'calio-addon') . '" />';
        echo '</label>';
        echo '<label class="calio-inventory-hud__threshold">';
        echo '<span>' . esc_html__('Low stock threshold', 'calio-addon') . ': <strong data-threshold-value>' . esc_html((string) $threshold) . '</strong></span>';
        echo '<input type="range" min="0" max="100" step="1" value="' . esc_attr((string) $threshold) . '" data-inventory-threshold />';
        echo '</label>';
        echo '<div class="calio-inventory-hud__buttons">';
        echo '<button type="button" class="button" data-inventory-refresh>' . esc_html__('Refresh', 'calio-addon') . '</button>';
        echo '<button type="button" class="button button-primary" data-inventory-export>' . esc_html__('Export to CSV', 'calio-addon') . '</button>';
        echo '</div>';
        echo '</div>';

        echo '<div class="calio-inventory-hud__status" data-inventory-status aria-live="polite"></div>';
        echo '<div class="calio-inventory-hud__table-wrap">';
        echo '<table class="widefat striped calio-inventory-hud__table">';
        echo '<thead><tr>';
        echo '<th scope="col">' . esc_html__('Product', 'calio-addon') . '</th>';
        echo '<th scope="col">' . esc_html__('SKU', 'calio-addon') . '</th>';
        echo '<th scope="col">' . esc_html__('Stock', 'calio-addon') . '</th>';
        echo '<th scope="col">' . esc_html__('Price', 'calio-addon') . '</th>';
        echo '</tr></thead>';
        echo '<tbody data-inventory-body>';
        foreach ($items as $item) {
            $this->render_inventory_row($item, $threshold);
        }
        echo '</tbody>';
        echo '</table>';
        echo '<p class="calio-inventory-hud__empty" data-inventory-empty hidden>' . esc_html__('No products match the current search.', 'calio-addon') . '</p>';
        echo '</div>';
        echo '</div>';
    }

    public function ajax_refresh_inventory(): void
    {
        check_ajax_referer(self::INVENTORY_NONCE_ACTION, 'nonce');

        if (!$this->can_view_inventory()) {
            wp_send_json_error(['message' => __('You are not allowed to view inventory data.', 'calio-addon')], 403);
        }

        if (!function_exists('wc_get_products')) {
            wp_send_json_error(['message' => __('WooCommerce is not available.', 'calio-addon')], 409);
        }

        $threshold = isset($_POST['threshold']) ? absint(wp_unslash($_POST['threshold'])) : 5;
        $threshold = min(100, $threshold);
        $items = $this->inventory_items($threshold);

        wp_send_json_success(
            [
                'items' => $items,
                'summary' => $this->inventory_summary($items, $threshold),
                'updatedAt' => wp_date(get_option('time_format')),
            ]
        );
    }

    /**
     * Renders enabled widget totals, names, version details, and release notes.
     */
    public function render(): void
    {
        $enabled_widgets = $this->enabled_widgets();
        $free_widgets = array_filter(
            $enabled_widgets,
            static fn(array $widget): bool => ($widget['tier'] ?? 'free') !== 'pro'
        );
        $pro_widgets = array_filter(
            $enabled_widgets,
            static fn(array $widget): bool => ($widget['tier'] ?? 'free') === 'pro'
        );
        $release_notes = $this->release_notes();
        $settings_url = admin_url('admin.php?page=' . CALIO_MENU_SLUG . '#calio_addon_dashboard_widgets');
        $changelog_url = 'https://wordpress.org/plugins/calio-addon/#developers';

        echo '<div class="calio-dashboard-widget">';
        echo '<div class="calio-dashboard-widget__stats">';
        $this->render_stat(
            (string) count($enabled_widgets),
            esc_html__('Active widgets', 'calio-addon')
        );
        $this->render_stat(
            (string) count($free_widgets),
            esc_html__('Free widgets', 'calio-addon')
        );
        $this->render_stat(
            (string) count($pro_widgets),
            esc_html__('Pro widgets', 'calio-addon')
        );
        echo '</div>';

        echo '<details class="calio-dashboard-widget__details">';
        echo '<summary>';
        echo esc_html(
            sprintf(
                /* translators: %d: number of enabled Calio widgets. */
                __('View %d active widgets', 'calio-addon'),
                count($enabled_widgets)
            )
        );
        echo '</summary>';

        if ($enabled_widgets === []) {
            echo '<p>' . esc_html__('No Calio widgets are currently enabled.', 'calio-addon') . '</p>';
        } else {
            echo '<ul class="calio-dashboard-widget__list">';
            foreach ($enabled_widgets as $widget) {
                $title = isset($widget['title']) ? (string) $widget['title'] : '';
                $tier = ($widget['tier'] ?? 'free') === 'pro' ? 'Pro' : 'Free';

                echo '<li>';
                echo '<span>' . esc_html($title) . '</span>';
                echo '<small>' . esc_html($tier) . '</small>';
                echo '</li>';
            }
            echo '</ul>';
        }
        echo '</details>';

        echo '<div class="calio-dashboard-widget__release">';
        echo '<div class="calio-dashboard-widget__release-heading">';
        echo '<strong>' . esc_html__('Latest update', 'calio-addon') . '</strong>';
        echo '<span>' . esc_html('v' . CALIO_VERSION) . '</span>';
        echo '</div>';
        echo '<ul>';
        foreach ($release_notes as $note) {
            echo '<li>' . esc_html($note) . '</li>';
        }
        echo '</ul>';
        echo '</div>';

        echo '<div class="calio-dashboard-widget__actions">';
        echo '<a class="button button-primary" href="' . esc_url($settings_url) . '">';
        echo esc_html__('Manage widgets', 'calio-addon');
        echo '</a>';
        echo '<a class="button" href="' . esc_url($changelog_url) . '" target="_blank" rel="noopener noreferrer">';
        echo esc_html__('Full changelog', 'calio-addon');
        echo '</a>';
        echo '</div>';
        echo '</div>';
    }

    /**
     * @return array<string, array<string, mixed>>
     */
    private function enabled_widgets(): array
    {
        $enabled_map = Settings::core_widget_map();
        $enabled_widgets = [];

        foreach (WidgetCatalog::all() as $slug => $widget) {
            if (empty($enabled_map[$slug]) || ProAccess::is_widget_locked($widget)) {
                continue;
            }

            $enabled_widgets[$slug] = $widget;
        }

        uasort(
            $enabled_widgets,
            static fn(array $first, array $second): int => strcasecmp(
                (string) ($first['title'] ?? ''),
                (string) ($second['title'] ?? '')
            )
        );

        return $enabled_widgets;
    }

    /**
     * @return string[]
     */
    private function release_notes(): array
    {
        $notes = [
            '1.11' => [
                __('Added the Image Comparison Slider with before/after images and draggable controls.', 'calio-addon'),
                __('Added editable labels, overlay color, and transition speed settings.', 'calio-addon'),
            ],
            '1.10' => [
                __('Added the WooCommerce Slider powered by Elementor Swiper.', 'calio-addon'),
                __('Expanded product queries, responsive layouts, navigation, and product action controls.', 'calio-addon'),
            ],
        ];

        return $notes[CALIO_VERSION] ?? [
            __('This version includes Calio widget and compatibility improvements.', 'calio-addon'),
        ];
    }

    private function render_stat(string $value, string $label): void
    {
        echo '<div class="calio-dashboard-widget__stat">';
        echo '<strong>' . esc_html($value) . '</strong>';
        echo '<span>' . esc_html($label) . '</span>';
        echo '</div>';
    }

    private function can_view_inventory(): bool
    {
        return current_user_can('manage_woocommerce') || current_user_can('manage_options');
    }

    /**
     * @return array<int, array{id: int, name: string, sku: string, stock: int|null, price: string, priceDisplay: string}>
     */
    private function inventory_items(int $threshold): array
    {
        $query = [
            'limit' => -1,
            'status' => get_post_stati(['show_in_admin_all_list' => true], 'names'),
            'orderby' => 'name',
            'order' => 'ASC',
            'return' => 'objects',
        ];
        $products = wc_get_products($query);
        $variations = wc_get_products(array_merge($query, ['type' => 'variation']));
        $items = [];

        foreach (array_merge($products, $variations) as $product) {
            if (!$product instanceof \WC_Product || isset($items[$product->get_id()])) {
                continue;
            }

            $stock = $product->get_stock_quantity();
            $price = (string) $product->get_price();
            $name = $product->is_type('variation')
                ? wp_strip_all_tags($product->get_formatted_name())
                : $product->get_name();

            $items[$product->get_id()] = [
                'id' => $product->get_id(),
                'name' => sanitize_text_field($name),
                'sku' => sanitize_text_field((string) $product->get_sku()),
                'stock' => is_numeric($stock) ? (int) $stock : null,
                'price' => $price !== '' ? wc_format_decimal($price, wc_get_price_decimals()) : '',
                'priceDisplay' => $price !== '' ? wp_strip_all_tags(wc_price((float) $price)) : '',
            ];
        }

        uasort(
            $items,
            static function (array $first, array $second) use ($threshold): int {
                $first_stock = $first['stock'];
                $second_stock = $second['stock'];
                $first_low = $first_stock !== null && $first_stock < $threshold;
                $second_low = $second_stock !== null && $second_stock < $threshold;

                if ($first_low !== $second_low) {
                    return $first_low ? -1 : 1;
                }

                if ($first_stock !== null && $second_stock !== null && $first_stock !== $second_stock) {
                    return $first_stock <=> $second_stock;
                }

                return strcasecmp($first['name'], $second['name']);
            }
        );

        return array_values($items);
    }

    /**
     * @param array<int, array{stock: int|null}> $items
     * @return array{total: int, low: int, out: int}
     */
    private function inventory_summary(array $items, int $threshold): array
    {
        $low = 0;
        $out = 0;

        foreach ($items as $item) {
            if ($item['stock'] === null) {
                continue;
            }

            if ($item['stock'] <= 0) {
                ++$out;
            }

            if ($item['stock'] < $threshold) {
                ++$low;
            }
        }

        return [
            'total' => count($items),
            'low' => $low,
            'out' => $out,
        ];
    }

    /**
     * @param array{name: string, sku: string, stock: int|null, price: string, priceDisplay: string} $item
     */
    private function render_inventory_row(array $item, int $threshold): void
    {
        $is_low = $item['stock'] !== null && $item['stock'] < $threshold;
        $stock_label = $item['stock'] === null
            ? __('Not managed', 'calio-addon')
            : (string) $item['stock'];
        $price_label = $item['priceDisplay'] !== '' ? $item['priceDisplay'] : __('Not set', 'calio-addon');

        echo '<tr class="' . esc_attr($is_low ? 'is-low-stock' : '') . '"';
        echo ' data-name="' . esc_attr(strtolower($item['name'])) . '"';
        echo ' data-sku="' . esc_attr(strtolower($item['sku'])) . '"';
        echo ' data-stock="' . esc_attr($item['stock'] === null ? '' : (string) $item['stock']) . '"';
        echo ' data-price="' . esc_attr($item['price']) . '">';
        echo '<td><strong>' . esc_html($item['name']) . '</strong></td>';
        echo '<td>' . esc_html($item['sku'] !== '' ? $item['sku'] : '-') . '</td>';
        echo '<td><span class="calio-stock-pill">' . esc_html($stock_label) . '</span></td>';
        echo '<td>' . esc_html($price_label) . '</td>';
        echo '</tr>';
    }

    private function render_inventory_stat(string $value, string $label, string $type): void
    {
        echo '<div class="calio-inventory-hud__stat is-' . esc_attr($type) . '">';
        echo '<strong data-inventory-stat="' . esc_attr($type) . '">' . esc_html($value) . '</strong>';
        echo '<span>' . esc_html($label) . '</span>';
        echo '</div>';
    }
}
