<?php

use MintyPHP\Http\SessionStoreInterface;
use MintyPHP\Module\Helpdesk\HelpdeskAuthorizationPolicy;
use MintyPHP\Module\Helpdesk\Service\DebitorCacheControl;
use MintyPHP\Module\Helpdesk\Service\DebitorDetailService;
use MintyPHP\Router;
use MintyPHP\Support\Guard;

Guard::requireLogin();
Guard::requireAbilityOrForbidden(HelpdeskAuthorizationPolicy::ABILITY_ACCESS);

gridRequireGetRequest();

$filters = gridParseFiltersFromSchemaFile(__DIR__ . '/debitor-contacts-filter-schema.php');
$request = requestInput();

$customerNo = (string) ($filters['customerNo'] ?? '');
$customerName = (string) ($filters['customerName'] ?? '');
$refreshRequested = DebitorCacheControl::parseRefreshFlag($request->query('refresh', ''));

if ($customerNo === '' || $customerName === '') {
    Router::json([
        'data' => [],
        'total' => 0,
        'type_options' => [],
        'meta' => [
            'cache_used' => false,
            'cache_bypassed' => $refreshRequested,
            'cache_refreshed' => false,
        ],
    ]);

    return;
}

// --- Session cache (lazy TTL = 300s) ---

$sessionStore = app(SessionStoreInterface::class);
$session = $sessionStore->all();
$tenantScope = DebitorCacheControl::resolveTenantScope($session);
if ($refreshRequested) {
    DebitorCacheControl::invalidateDebitorCaches($sessionStore, $tenantScope, $customerNo, true);
}

$cacheKey = DebitorCacheControl::contactsKey($tenantScope, $customerNo);
$cacheTtl = DebitorCacheControl::TTL_STANDARD_SECONDS;
$cached = $sessionStore->get($cacheKey);
$allContacts = null;
$cacheUsed = false;
$serviceMeta = [
    'source' => 'primary.company_name',
    'fallback_used' => false,
    'fallback_reason' => '',
];

if (!$refreshRequested && is_array($cached) && isset($cached['fetched_at']) && (time() - (int) $cached['fetched_at']) < $cacheTtl) {
    $allContacts = $cached['contacts'] ?? [];
    $cacheUsed = true;
    if (is_array($cached['service_meta'] ?? null)) {
        $serviceMeta = [
            'source' => (string) ($cached['service_meta']['source'] ?? $serviceMeta['source']),
            'fallback_used' => (bool) ($cached['service_meta']['fallback_used'] ?? false),
            'fallback_reason' => (string) ($cached['service_meta']['fallback_reason'] ?? ''),
        ];
    }
}

if ($allContacts === null) {
    $service = app(DebitorDetailService::class);
    $result = $service->loadContacts($customerNo, $customerName);

    if (!($result['ok'] ?? false)) {
        $resultMeta = is_array($result['meta'] ?? null) ? $result['meta'] : [];
        Router::json([
            'data' => [],
            'total' => 0,
            'type_options' => [],
            'meta' => [
                'cache_used' => $cacheUsed,
                'cache_bypassed' => $refreshRequested,
                'cache_refreshed' => $refreshRequested,
                'source' => (string) ($resultMeta['source'] ?? $serviceMeta['source']),
                'fallback_used' => (bool) ($resultMeta['fallback_used'] ?? false),
                'fallback_reason' => (string) ($resultMeta['fallback_reason'] ?? ''),
            ],
        ]);

        return;
    }

    $allContacts = $result['contacts'] ?? [];
    $resultMeta = is_array($result['meta'] ?? null) ? $result['meta'] : [];
    $serviceMeta = [
        'source' => (string) ($resultMeta['source'] ?? $serviceMeta['source']),
        'fallback_used' => (bool) ($resultMeta['fallback_used'] ?? false),
        'fallback_reason' => (string) ($resultMeta['fallback_reason'] ?? ''),
    ];

    $sessionStore->set($cacheKey, [
        'contacts' => $allContacts,
        'service_meta' => $serviceMeta,
        'fetched_at' => time(),
    ]);
}

// --- Collect unique types for filter options ---

$typeSet = [];
foreach ($allContacts as $contact) {
    $type = trim((string) ($contact['Type'] ?? ''));
    if ($type !== '' && !isset($typeSet[$type])) {
        $typeSet[$type] = true;
    }
}
ksort($typeSet);
$typeOptions = [];
foreach (array_keys($typeSet) as $type) {
    $typeOptions[] = ['id' => $type, 'description' => $type];
}

// --- PHP-side filtering ---

$search = trim((string) ($filters['search'] ?? ''));
$typeFilter = trim((string) ($filters['type'] ?? ''));
$order = (string) ($filters['order'] ?? 'Name');
$dir = (string) ($filters['dir'] ?? 'asc');
$limit = (int) ($filters['limit'] ?? 10);
$offset = (int) ($filters['offset'] ?? 0);

$filtered = $allContacts;

// Search: stripos on Name + Job_Title + E_Mail + Phone_No + Mobile_Phone_No
if ($search !== '') {
    $searchLower = mb_strtolower($search);
    $filtered = array_values(array_filter($filtered, static function (array $contact) use ($searchLower): bool {
        $haystack = mb_strtolower(
            ($contact['Name'] ?? '') . ' '
            . ($contact['Job_Title'] ?? '') . ' '
            . ($contact['E_Mail'] ?? '') . ' '
            . ($contact['Phone_No'] ?? '') . ' '
            . ($contact['Mobile_Phone_No'] ?? '')
        );

        return str_contains($haystack, $searchLower);
    }));
}

// Type filter
if ($typeFilter !== '') {
    $filtered = array_values(array_filter($filtered, static function (array $contact) use ($typeFilter): bool {
        return trim((string) ($contact['Type'] ?? '')) === $typeFilter;
    }));
}

// --- Sorting ---

$total = count($filtered);

usort($filtered, static function (array $a, array $b) use ($order, $dir): int {
    $va = (string) ($a[$order] ?? '');
    $vb = (string) ($b[$order] ?? '');
    $cmp = strnatcasecmp($va, $vb);

    return $dir === 'desc' ? -$cmp : $cmp;
});

// --- Pagination ---

$rows = array_slice($filtered, $offset, $limit);

// --- Row preparation ---

$preparedRows = [];
foreach ($rows as $contact) {
    $preparedRows[] = [
        'Name' => (string) ($contact['Name'] ?? ''),
        'Type' => (string) ($contact['Type'] ?? ''),
        'Job_Title' => (string) ($contact['Job_Title'] ?? ''),
        'E_Mail' => (string) ($contact['E_Mail'] ?? ''),
        'Phone_No' => (string) ($contact['Phone_No'] ?? ''),
        'Mobile_Phone_No' => (string) ($contact['Mobile_Phone_No'] ?? ''),
    ];
}

Router::json([
    'data' => $preparedRows,
    'total' => max(0, $total),
    'type_options' => $typeOptions,
    'meta' => [
        'cache_used' => $cacheUsed,
        'cache_bypassed' => $refreshRequested,
        'cache_refreshed' => $refreshRequested,
        'source' => $serviceMeta['source'],
        'fallback_used' => $serviceMeta['fallback_used'],
        'fallback_reason' => $serviceMeta['fallback_reason'],
    ],
]);
