<?php
/**
 * BookiFlex NotificationLog Extension
 *
 * @package    BookiFlex
 * @subpackage NotificationLog
 * @author     BookiFlex
 * @copyright  Copyright (c) 2025 BookiFlex
 * @license    GPL-2.0-or-later
 *
 * @link       https://bookiflex.com
 */

declare(strict_types=1);

namespace BookiFlex\Extensions\NotificationLog\Admin\CTL;

use BookiFlex\Core\Contract\PluginInterface;
use BookiFlex\Core\Util\Request;
use BookiFlex\Extensions\Notification\Model\NotificationStatus;
use BookiFlex\Extensions\NotificationLog\Admin\Menu\NotificationLogMenu;
use BookiFlex\Extensions\NotificationLog\Admin\QueryFilter\NotificationLogQueryFilter;
use BookiFlex\Extensions\NotificationLog\Admin\Transformer\NotificationLogTransformer;
use BookiFlex\Extensions\NotificationLog\Service\NotificationLogService;

defined('ABSPATH') || exit;

class NotificationLogTableList extends \WP_List_Table
{
    public const NAME = 'NOTIFICATION_LOG_TABLE_LIST';
    public const ITEMS_PER_PAGE_OPTION = 20;

    private readonly PluginInterface $plugin;

    public function __construct(PluginInterface $plugin)
    {
        $this->plugin = $plugin;
        parent::__construct([
            'singular' => __('Notification', 'bookiflex'),
            'plural'   => __('Notifications', 'bookiflex'),
            'ajax'     => false,
        ]);
    }

    public function get_name(): string
    {
        return self::NAME;
    }

    public function get_columns(): array
    {
        return [
            'reservation_number' => __('Reservation #', 'bookiflex'),
            'event'              => __('Event', 'bookiflex'),
            'stakeholder'        => __('Recipient', 'bookiflex'),
            'status'             => __('Status', 'bookiflex'),
            'send_time'          => __('Send Time', 'bookiflex'),
            'attempt'            => __('Attempts', 'bookiflex'),
            'actions'            => __('Actions', 'bookiflex'),
        ];
    }

    public function get_sortable_columns(): array
    {
        return [
            'event'       => ['event', false],
            'stakeholder' => ['stakeholder', false],
            'status'      => ['status', false],
            'send_time'   => ['send_time', true],
            'attempt'     => ['attempt', false],
        ];
    }

    protected function get_default_hidden_columns(): array
    {
        return [];
    }

    public function get_hidden_columns(): array
    {
        $hidden = get_user_option('manage' . $this->screen->id . 'columnshidden');

        if ($hidden === false) {
            $hidden = $this->get_default_hidden_columns();
        }

        return $hidden;
    }

    public function column_default($item, $column_name): string
    {
        return esc_html($item[$column_name] ?? '');
    }

    protected function column_reservation_number($item): string
    {
        $number = $item['reservation_number'];
        if ($number === '—') {
            return '—';
        }

        $url = admin_url('admin.php?page=bookiflex-reservations&action=edit&reservation_number=' . urlencode($number));
        return sprintf(
            '<a href="%s" data-turbo="false">%s</a>',
            esc_url($url),
            esc_html($number)
        );
    }

    protected function column_stakeholder($item): string
    {
        return ucfirst(esc_html($item['stakeholder']));
    }

    protected function column_status($item): string
    {
        $labels = [
            NotificationStatus::PENDING   => __('Pending', 'bookiflex'),
            NotificationStatus::SENT      => __('Sent', 'bookiflex'),
            NotificationStatus::FAILED    => __('Failed', 'bookiflex'),
            NotificationStatus::CANCELLED => __('Cancelled', 'bookiflex'),
        ];

        $variant = match ($item['status']) {
            NotificationStatus::SENT      => 'success',
            NotificationStatus::FAILED    => 'danger',
            NotificationStatus::CANCELLED => 'neutral',
            default                       => 'warning',
        };

        $label = $labels[$item['status']] ?? $item['status'];

        return sprintf('<sl-badge variant="%s">%s</sl-badge>', $variant, esc_html($label));
    }

    protected function column_attempt($item): string
    {
        return esc_html((string) $item['attempt']);
    }

    protected function column_actions($item): string
    {
        if (!$item['has_snapshot']) {
            return sprintf(
                '<sl-tooltip content="%s"><sl-button size="small" disabled><sl-icon slot="prefix" name="send" label="%s"></sl-icon>%s</sl-button></sl-tooltip>',
                esc_attr__('No snapshot available for this notification', 'bookiflex'),
                esc_attr__('Resend', 'bookiflex'),
                esc_html__('Resend', 'bookiflex')
            );
        }

        $preview = sprintf(
            '<sl-button size="small" data-action="preview-notification" data-sid="%s" data-turbo="false">' .
            '<sl-icon slot="prefix" name="eye" label="%s"></sl-icon>%s</sl-button>',
            esc_attr($item['sid']),
            esc_attr__('Preview', 'bookiflex'),
            esc_html__('Preview', 'bookiflex')
        );

        $resend = sprintf(
            '<sl-button size="small" data-action="resend-notification" data-sid="%s" data-turbo="false">' .
            '<sl-icon slot="prefix" name="send" label="%s"></sl-icon>%s</sl-button>',
            esc_attr($item['sid']),
            esc_attr__('Resend', 'bookiflex'),
            esc_html__('Resend', 'bookiflex')
        );

        return $preview . ' ' . $resend;
    }

    public function get_primary_column_name(): string
    {
        return 'reservation_number';
    }

    public function prepare_items(): void
    {
        $columns  = $this->get_columns();
        $hidden   = $this->get_hidden_columns();
        $sortable = $this->get_sortable_columns();
        $this->_column_headers = [$columns, $hidden, $sortable];

        $service     = $this->plugin->getContainer()->get(NotificationLogService::class);
        $transformer = new NotificationLogTransformer();

        $per_page     = $this->get_items_per_page(NotificationLogMenu::PER_PAGE_FIELD, self::ITEMS_PER_PAGE_OPTION);
        $current_page = $this->get_pagenum();

        $filter = new NotificationLogQueryFilter(
            reservationNumber: Request::getString('s') ?: null,
            status: Request::getString('status') ?: null,
            stakeholder: Request::getString('stakeholder') ?: null,
            orderBy: Request::getString('orderby', 'send_time'),
            order: Request::getString('order', 'DESC'),
            limit: $per_page,
            offset: max(0, ($current_page - 1) * $per_page),
        );

        $notifications = $service->list($filter);
        $total         = $service->count($filter);

        $this->items = $transformer->transformCollection($notifications);

        $this->set_pagination_args([
            'total_items' => $total,
            'per_page'    => $per_page,
            'total_pages' => (int) ceil($total / max(1, $per_page)),
        ]);
    }

    public function no_items(): void
    {
        echo esc_html__('No notifications found.', 'bookiflex');
    }

    public function get_views(): array
    {
        $statuses = [
            NotificationStatus::PENDING   => __('Pending', 'bookiflex'),
            NotificationStatus::SENT      => __('Sent', 'bookiflex'),
            NotificationStatus::FAILED    => __('Failed', 'bookiflex'),
            NotificationStatus::CANCELLED => __('Cancelled', 'bookiflex'),
        ];

        $pageSlug      = Request::getString('page');
        $currentStatus = Request::getString('status');
        $baseUrl       = admin_url('admin.php');

        $allUrl   = add_query_arg('page', $pageSlug, $baseUrl);
        $allClass = $currentStatus === '' ? ' class="current"' : '';

        $links = [
            'all' => sprintf(
                '<a href="%s" aria-current="page"%s>%s</a>',
                esc_url($allUrl),
                $allClass,
                esc_html__('All', 'bookiflex')
            ),
        ];

        foreach ($statuses as $status => $label) {
            $url     = add_query_arg(['page' => $pageSlug, 'status' => $status], $baseUrl);
            $class   = ($currentStatus === $status) ? ' class="current"' : '';
            $links[] = sprintf(
                '<a href="%s"%s>%s</a>',
                esc_url($url),
                $class,
                esc_html($label)
            );
        }

        return $links;
    }
}
