<?php

declare(strict_types=1);

function loadFollowupSettings(): array
{
    $fallback = buildFollowupFallbackSettings();
    $cacheFile = (string) config(
        'FOLLOWUP_SETTINGS_CACHE_FILE',
        __DIR__ . '/../storage/cache/followups.json'
    );
    $ttl = max(0, (int) config('FOLLOWUP_SETTINGS_CACHE_TTL', 300));
    $cached = readJsonFile($cacheFile, []);

    if (($cached['version'] ?? 0) === 1
        && ($cached['expires_at'] ?? 0) > time()
        && is_array($cached['data'] ?? null)
    ) {
        return $cached['data'];
    }

    try {
        $loaded = loadFollowupSettingsFromBitrixList();
        if (($loaded['stages'] ?? []) === []) {
            return $fallback;
        }

        writeJsonFile($cacheFile, [
            'version' => 1,
            'expires_at' => time() + $ttl,
            'data' => $loaded,
        ]);

        return $loaded;
    } catch (Throwable $exception) {
        logMessage('warning', 'Followup settings list load failed; environment fallback used', [
            'error' => $exception->getMessage(),
        ]);

        return $fallback;
    }
}

function loadFollowupSettingsFromBitrixList(): array
{
    $listCode = trim((string) config('FOLLOWUP_SETTINGS_LIST_CODE', 'darex_ai_followups'));
    $list = findBitrixListByCode($listCode);
    if ($list === null) {
        throw new RuntimeException('Bitrix followup settings list not found: ' . $listCode);
    }

    $iblockTypeId = (string) ($list['_IBLOCK_TYPE_ID'] ?? 'lists');
    $iblockId = (int) ($list['ID'] ?? 0);
    $fieldsResponse = bitrixCall('lists.field.get', [
        'IBLOCK_TYPE_ID' => $iblockTypeId,
        'IBLOCK_ID' => $iblockId,
    ]);
    $properties = mapFollowupFieldCodes((array) ($fieldsResponse['result'] ?? []));
    foreach (['STAGE_NUMBER', 'DELAY_MINUTES', 'MESSAGE', 'MESSAGE_NEED_CITY', 'MESSAGE_NEED_PHONE'] as $code) {
        if (($properties[$code] ?? '') === '') {
            throw new RuntimeException('Followup list field not found: ' . $code);
        }
    }

    $elementsResponse = bitrixCall('lists.element.get', [
        'IBLOCK_TYPE_ID' => $iblockTypeId,
        'IBLOCK_ID' => $iblockId,
        'FILTER' => ['ACTIVE' => 'Y'],
    ]);
    $stages = [];
    foreach ((array) ($elementsResponse['result'] ?? []) as $element) {
        $element = (array) $element;
        $stageNumber = (int) followupElementProperty($element, $properties['STAGE_NUMBER']);
        $delayMinutes = (int) followupElementProperty($element, $properties['DELAY_MINUTES']);
        if ($stageNumber <= 0 || $delayMinutes <= 0) {
            continue;
        }

        $stages[] = [
            'index' => $stageNumber - 1,
            'stage_number' => $stageNumber,
            'delay_seconds' => $delayMinutes * 60,
            'message' => followupElementProperty($element, $properties['MESSAGE']),
            'message_need_city' => followupElementProperty($element, $properties['MESSAGE_NEED_CITY']),
            'message_need_phone' => followupElementProperty($element, $properties['MESSAGE_NEED_PHONE']),
            'element_id' => (string) ($element['ID'] ?? ''),
            'sort' => (int) ($element['SORT'] ?? ($stageNumber * 100)),
        ];
    }

    usort($stages, static function (array $left, array $right): int {
        return [$left['stage_number'], $left['sort']] <=> [$right['stage_number'], $right['sort']];
    });

    return [
        'source' => 'bitrix_list',
        'list_code' => $listCode,
        'list_id' => $iblockId,
        'stages' => array_values($stages),
    ];
}

function buildFollowupFallbackSettings(): array
{
    $offsets = normalizeFollowupSettingOffsets(config('FOLLOWUP_OFFSETS_SECONDS', []));
    $generic = (array) config('FOLLOWUP_MESSAGES', []);
    $needCity = (array) config('FOLLOWUP_MESSAGES_NEED_CITY', []);
    $needPhone = (array) config('FOLLOWUP_MESSAGES_NEED_PHONE', []);
    $stages = [];

    foreach ($offsets as $index => $offset) {
        $stages[] = [
            'index' => $index,
            'stage_number' => $index + 1,
            'delay_seconds' => $offset,
            'message' => trim((string) ($generic[$index] ?? '')),
            'message_need_city' => trim((string) ($needCity[$index] ?? '')),
            'message_need_phone' => trim((string) ($needPhone[$index] ?? '')),
        ];
    }

    return ['source' => 'environment', 'stages' => $stages];
}

function normalizeFollowupSettingOffsets($value): array
{
    if (is_string($value)) {
        $value = array_map('trim', explode(',', $value));
    }

    $result = [];
    foreach ((array) $value as $seconds) {
        $seconds = (int) $seconds;
        if ($seconds > 0) {
            $result[] = $seconds;
        }
    }

    return $result;
}

function mapFollowupFieldCodes(array $fields): array
{
    $result = [];
    foreach ($fields as $fieldId => $field) {
        $field = (array) $field;
        $code = trim((string) ($field['CODE'] ?? ''));
        if ($code === '') {
            continue;
        }

        $id = trim((string) $fieldId);
        $result[$code] = str_starts_with($id, 'PROPERTY_') ? $id : 'PROPERTY_' . $id;
    }

    return $result;
}

function followupElementProperty(array $element, string $property): string
{
    return extractPromptPropertyValueFromElement($element, $property);
}

function followupStageByIndex(array $settings, int $index): array
{
    foreach ((array) ($settings['stages'] ?? []) as $stage) {
        if ((int) ($stage['index'] ?? -1) === $index) {
            return (array) $stage;
        }
    }

    return [];
}
