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

declare(strict_types=1);

namespace BookiFlex\Core\Admin\CTL;

use BookiFlex\Core\Admin\Menu\CustomerMenu;
use BookiFlex\Core\Admin\Transformer\CustomerTableListTransformer;
use BookiFlex\Core\Contract\PluginInterface;
use BookiFlex\Core\Model\Reservation\ReservationStatus;
use BookiFlex\Core\Repository\CustomerQueryFilter;
use BookiFlex\Core\Service\Customer\CustomerListService;
use BookiFlex\Core\Util\Request;

defined( 'ABSPATH' ) || exit;

class CustomerTableList extends \WP_List_Table
{
    public const NAME = 'CUSTOMER_TABLE_LIST';
    public const ITEMS_PER_PAGE_OPTION = 20;
    public const DATE_FORMAT = 'Y-m-d H:i:s';

    private readonly PluginInterface $plugin;
    private ?array $pendingNotice = null;

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

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

    /**
     * Add screen options for managing table columns and per page
     * This should be called from the admin page where this table is displayed
     */
    public static function add_screen_options(): void
    {
        // Add filter for screen options to handle column visibility
    }

    /**
     * Define table columns
     */
    public function get_columns(): array
    {
        return [
            'cb'           => '<input type="checkbox" />',
            'id'           => __('ID', 'bookiflex'),
            'first_name'   => __('Name', 'bookiflex'),
            'email'        => __('Email', 'bookiflex'),
            'phone'        => __('Phone', 'bookiflex'),
            'reservations' => __('Reservations', 'bookiflex'),
            'payments'     => __('Payments', 'bookiflex'),
            'created_at'   => __('Created At', 'bookiflex'),
            'updated_at'   => __('Updated At', 'bookiflex'),
//            'actions'      => __('Actions', 'bookiflex'),
        ];
    }

    /**
     * Define which columns are sortable
     */
    public function get_sortable_columns(): array
    {
        return [
            'id'           => ['id', false],
            'first_name'   => ['first_name', true], // Default sort ascending
            'email'        => ['email', false],
            'phone'        => ['phone', false],
//            'reservations' => ['reservations', false],
//            'payments'     => ['payments', false],
            'created_at'   => ['created_at', false],
            'updated_at'   => ['updated_at', false],
        ];
    }

    /**
     * Define default hidden columns
     */
    protected function get_default_hidden_columns(): array
    {
        return [
            'id',
            'updated_at',
//	        'actions',
        ];
    }

    /**
     * Get user's hidden columns preference
     */
    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;
    }

    /**
     * Default column display method
     */
    public function column_default($item, $column_name): string
    {
        return $item[$column_name] ?? '';
    }

    /**
     * Display checkbox column
     */
    protected function column_cb($item): string
    {
        return sprintf(
            '<label class="screen-reader-text" for="customer_%1$d">%2$s</label>' .
            '<input type="checkbox" name="customers[]" id="customer_%1$d" value="%1$d" />',
            $item['id'],
            $item['first_name'] . ' ' . $item['last_name']
        );
    }

    /**
     * Display ID column
     */
    protected function column_id($item): string
    {
        return (string) $item['id'];
    }

    /**
     * Display customer name column
     */
	protected function column_first_name($item): string
	{
		return sprintf(
			'<span>%s %s</span><br/><a href="mailto:%s" target="_blank">%s</a>',
			$item['first_name'],
			$item['last_name'],
			$item['email'],
			$item['email']
		);
	}

    /**
     * Display email column
     */
    protected function column_email($item): string
    {
        return sprintf('<a href="mailto:%s">%s</a>', $item['email'], $item['email']);
    }

    /**
     * Display phone column
     */
    protected function column_phone($item): string
    {
        return $item['phone'] ?: '-';
    }

    /**
     * Display reservations count column
     */
    protected function column_reservations($item): string
    {
        $link = admin_url('admin.php?page=bookiflex-reservations&customer_id=' . $item['id']);
        $count = (int) ($item['reservations'] ?? 0);

        return sprintf(
            '<a href="%s" data-turbo="false"><sl-badge variant="primary">%d</sl-badge></a>',
            $link,
            $count
        );
    }

    /**
     * Display payments count column
     */
    protected function column_payments($item): string
    {
        $link = admin_url('admin.php?page=bookiflex-payments&client_id=' . $item['id']);
        $count = (int) ($item['payments'] ?? 0);

        return sprintf(
            '<a href="%s" data-turbo="false"><sl-badge variant="warning">%d</sl-badge></a>',
            $link,
            $count
        );
    }

    /**
     * Display created at column
     */
    protected function column_created_at($item): string
    {
        $date = \DateTimeImmutable::createFromFormat(self::DATE_FORMAT, $item['created_at']);
        return $date ? $date->format(self::DATE_FORMAT) : $item['created_at'];
    }

    /**
     * Display updated at column
     */
    protected function column_updated_at($item): string
    {
        if (empty($item['updated_at'])) {
            return '-';
        }

        $date = \DateTimeImmutable::createFromFormat(self::DATE_FORMAT, $item['updated_at']);
        return $date ? $date->format(self::DATE_FORMAT) : $item['updated_at'];
    }

    /**
     * Display actions column
     */
    protected function column_actions($item): string
    {
        return sprintf(
            '<sl-button size="small" data-action="show-customer-details" data-id="%s" data-turbo="false">' .
            '<sl-icon slot="prefix" name="person-vcard" label="Show details"></sl-icon>%s</sl-button>',
            $item['id'],
            __('Details', 'bookiflex')
        );
    }

    /**
     * Get primary column for mobile display
     */
    public function get_primary_column_name(): string
    {
        return 'first_name';
    }

    /**
     * Prepare table items for display
     */
    public function prepare_items(): void
    {
        // Process bulk actions before preparing items
        $this->process_bulk_action();

        // Set up column headers
        $columns = $this->get_columns();
        $hidden = $this->get_hidden_columns();
        $sortable = $this->get_sortable_columns();
        $this->_column_headers = [$columns, $hidden, $sortable];

        // Get service and transformer from container
        $service = $this->plugin->getContainer()->get(CustomerListService::class);
        $transformer = new CustomerTableListTransformer();

        // Pagination setup
        $per_page = $this->get_items_per_page(CustomerMenu::PER_PAGE_FIELD, self::ITEMS_PER_PAGE_OPTION);
        $current_page = $this->get_pagenum();

        // Create filter from request - explicitly get each parameter
        $filter = new CustomerQueryFilter(
            status: Request::getKey('status') ?: null,
            searchTerm: Request::getString('s') ?: null,
            orderBy: Request::getKey('orderby', 'first_name'),
            order: Request::getKey('order', 'ASC'),
            limit: $per_page,
            offset: max(0, ($current_page - 1) * $per_page),
        );

        // Get enriched data from service
        $enrichedData = $service->getCustomers($filter);

        // Transform for display
        $this->items = $transformer->transform($enrichedData);

        // Count total items
        $total_items = $service->countCustomers($filter);

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

    /**
     * Display message when no items found
     */
    public function no_items(): void
    {
	    echo esc_html__('No customers available.', 'bookiflex');
    }

    /**
     * Get status filter links for table navigation with counts
     */
    public function get_views(): array
    {
        $status_links = [];
        $statuses = [
            'ALL'             => __('All', 'bookiflex'),
            ReservationStatus::STATUS_WAITING_PAYMENT => __('Waiting payment', 'bookiflex'),
            ReservationStatus::STATUS_OVERDUE         => __('Overdue', 'bookiflex'),
        ];

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

        // Get service from container
        $service = $this->plugin->getContainer()->get(CustomerListService::class);

        // Create filter without status constraint - explicitly get each parameter
        $filter = new CustomerQueryFilter(
            status: null, // No status filter for counts
            searchTerm: Request::getString('s') ?: null,
            orderBy: 'first_name',
            order: 'ASC',
            limit: 0,
            offset: 0,
        );

        // Get counts for each status
        $statusCounts = $service->getStatusCounts($filter);

        // Get total count (all customers matching search)
        $totalCount = $service->countCustomers($filter);

        // Add 'ALL' count
        $status_counts = array_merge(['ALL' => $totalCount], $statusCounts);

        foreach ($statuses as $status => $label) {
            $count = $status_counts[$status] ?? 0;
            $is_current = ($currentStatus === $status) ||
                ($currentStatus === '' && $status === 'ALL');

            $current_class = $is_current ? ' class="current"' : '';
            $css_class = 'status-' . strtolower($status);

            if ($status === 'ALL') {
                $url = add_query_arg('page', $pageSlug, $baseUrl);
            } else {
                $url = add_query_arg(
                    [
                        'page'   => $pageSlug,
                        'status' => $status,
                    ],
                    $baseUrl
                );
            }

            $status_links[$css_class] = sprintf(
                '<a href="%s"%s>%s <span class="count">(%d)</span></a>',
                esc_url($url),
                $current_class,
                esc_html($label),
                $count
            );
        }

        return $status_links;
    }

    /**
     * Define bulk actions
     */
    public function get_bulk_actions(): array
    {
        return [
            'delete' => __('Delete', 'bookiflex'),
        ];
    }

    /**
     * Process bulk actions
     */
    public function process_bulk_action(): void
    {
        // Check if bulk action is being performed
        if ('delete' !== $this->current_action()) {
            return;
        }

        // Verify nonce for security
        if (!wp_verify_nonce(Request::getNonce(), 'bulk-customers')) {
            wp_die(esc_html__('Security check failed', 'bookiflex'));
        }

        // Check user permissions
        if (!current_user_can('manage_options')) {
            wp_die(esc_html__('You do not have permission to delete customers', 'bookiflex'));
        }

        // Get selected customer IDs - already sanitized as positive integers
        $customer_ids = Request::getIntArray('customers');

        if (empty($customer_ids)) {
            $this->add_admin_notice('error', __('No customers selected for deletion', 'bookiflex'));
            return;
        }

        // Perform deletion
        $deleted_count = $this->delete_customers($customer_ids);

        if ($deleted_count > 0) {
            /* translators: %d: number of customers deleted */
            $message = _n(
                '%d customer deleted successfully',
                '%d customers deleted successfully',
                $deleted_count,
                'bookiflex'
            );
            $message = sprintf($message, $deleted_count);
            $this->add_admin_notice('success', $message);
        } else {
            $this->add_admin_notice('error', __('Failed to delete customers', 'bookiflex'));
        }
    }

    /**
     * Delete customers via service
     */
    private function delete_customers(array $customer_ids): int
    {
        if (empty($customer_ids)) {
            return 0;
        }

        $service = $this->plugin->getContainer()->get(CustomerListService::class);

        // Delete via service (handles fetching details before deletion)
        $result = $service->deleteCustomers($customer_ids);

        return $result['deleted'];
    }

    /**
     * Add admin notice
     */
    private function add_admin_notice(string $type, string $message): void
    {
        $this->plugin->addAction('admin_notices', [$this, 'displayAdminNotice']);
        $this->pendingNotice = ['type' => $type, 'message' => $message];
    }

    /**
     * Display pending admin notice
     */
    public function displayAdminNotice(): void
    {
        if (!isset($this->pendingNotice)) {
            return;
        }

        $class = $this->pendingNotice['type'] === 'error' ? 'notice-error' : 'notice-success';
        printf(
            '<div class="notice %s is-dismissible"><p>%s</p></div>',
            esc_attr($class),
            esc_html($this->pendingNotice['message'])
        );

        unset($this->pendingNotice);
    }
}
