<?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\Service\Customer;

use BookiFlex\Core\Model\Customer\Customer;
use BookiFlex\Core\Repository\CustomerQueryFilter;
use BookiFlex\Core\Repository\CustomerRepository;

defined( 'ABSPATH' ) || exit;

/**
 * Service for retrieving and enriching customer data for admin list display.
 *
 * This service orchestrates:
 * - Fetching customers from repository with filters and pagination
 * - Enriching customer data with reservation and payment counts
 * - Managing deletion with audit trail
 *
 * @package BookiFlex\Core\Service\Customer
 */
class CustomerListService
{
    public function __construct(
        private readonly CustomerRepository $customerRepository,
    ) {
    }

    /**
     * Get customers for table list with counts enrichment.
     *
     * Returns structure with:
     * - customers: Customer[] - Domain model entities
     * - counts: array - Reservation and payment counts indexed by customer ID
     *
     * @param CustomerQueryFilter $filter Query filters and pagination
     * @return array{customers: Customer[], counts: array<int, array{reservations: int, payments: int}>}
     */
    public function getCustomers(CustomerQueryFilter $filter): array
    {
        // Get domain models from repository
        $customers = $this->customerRepository->findPaginated($filter);

        if (empty($customers)) {
            return [
                'customers' => [],
                'counts' => [],
            ];
        }

        // Get customer IDs
        $customerIds = array_map(fn($customer) => $customer->getId(), $customers);

        // Get aggregated counts (reservations and payments)
        $counts = $this->customerRepository->getCustomerCounts($customerIds);

        // Return enriched structure
        return [
            'customers' => $customers,
            'counts' => $counts,
        ];
    }

    /**
     * Count total customers matching filters.
     *
     * @param CustomerQueryFilter $filter Query filters (pagination ignored)
     * @return int Total count
     */
    public function countCustomers(CustomerQueryFilter $filter): int
    {
        return $this->customerRepository->countFiltered($filter);
    }

    /**
     * Get status distribution for filter tabs.
     *
     * Returns count of customers grouped by reservation status.
     * Typically called with filter that has no status constraint.
     *
     * @param CustomerQueryFilter $filter Query filters (status typically null)
     * @return array<string, int> Map of status => count
     */
    public function getStatusCounts(CustomerQueryFilter $filter): array
    {
        return $this->customerRepository->getStatusCounts($filter);
    }

    /**
     * Delete customers and return audit data.
     *
     * Returns:
     * - deleted: int - Number of deleted customers
     * - customers: Customer[] - Deleted customer entities (for logging)
     *
     * @param int[] $customerIds Array of customer IDs to delete
     * @return array{deleted: int, customers: Customer[]}
     */
    public function deleteCustomers(array $customerIds): array
    {
        if (empty($customerIds)) {
            return [
                'deleted' => 0,
                'customers' => [],
            ];
        }

        // Get customer details before deletion (for audit trail)
        $customers = $this->customerRepository->findByIdsWithRelations($customerIds);

        // Delete customers
        $deletedCount = $this->customerRepository->deleteByIds($customerIds);

        return [
            'deleted' => $deletedCount,
            'customers' => $customers,
        ];
    }
}