<?php

declare(strict_types=1);

function chatHistoryKey(array $context): string
{
    $dialogId = trim((string) ($context['dialog_id'] ?? ''));
    if ($dialogId !== '') {
        return 'dialog:' . $dialogId;
    }

    $chatId = trim((string) ($context['chat_id'] ?? ''));
    if ($chatId !== '') {
        return 'chat:' . $chatId;
    }

    return 'default';
}

function getChatHistory(array $context): array
{
    $history = readJsonFile((string) config('CHAT_HISTORY_FILE'), ['chats' => []]);
    $key = chatHistoryKey($context);
    $messages = $history['chats'][$key]['messages'] ?? [];

    return is_array($messages) ? $messages : [];
}

function getChatStoredContext(array $context): array
{
    $history = readJsonFile((string) config('CHAT_HISTORY_FILE'), ['chats' => []]);
    $key = chatHistoryKey($context);
    $storedContext = $history['chats'][$key]['context'] ?? [];

    return is_array($storedContext) ? $storedContext : [];
}

function appendChatHistory(array $context, string $role, string $content): void
{
    $role = $role === 'assistant' ? 'assistant' : 'user';
    $content = trim($content);
    if ($content === '') {
        return;
    }

    $file = (string) config('CHAT_HISTORY_FILE');
    $history = readJsonFile($file, ['chats' => []]);
    $key = chatHistoryKey($context);

    if (!isset($history['chats'][$key]) || !is_array($history['chats'][$key])) {
        $history['chats'][$key] = [
            'context' => $context,
            'messages' => [],
        ];
    }

    $history['chats'][$key]['context'] = $context;
    $history['chats'][$key]['updated_at'] = date('c');

    if ($role === 'user') {
        unset($history['chats'][$key]['followup_sent_at']);
        unset($history['chats'][$key]['followup_for_message_at']);
        unset($history['chats'][$key]['followup_started_at']);
        unset($history['chats'][$key]['followups']);
        unset($history['chats'][$key]['no_response_marked_at']);
        unset($history['chats'][$key]['followups_stopped_at']);
        unset($history['chats'][$key]['followups_stopped_reason']);
    }

    $history['chats'][$key]['messages'][] = [
        'role' => $role,
        'content' => $content,
        'created_at' => date('c'),
    ];

    $maxMessages = max(2, (int) config('CHAT_HISTORY_MAX_MESSAGES', 20));
    $history['chats'][$key]['messages'] = array_slice($history['chats'][$key]['messages'], -$maxMessages);

    writeJsonFile($file, $history);
}

function markChatFollowupsStopped(string $chatKey, string $reason): void
{
    $file = (string) config('CHAT_HISTORY_FILE');
    $history = readJsonFile($file, ['chats' => []]);
    if (!isset($history['chats'][$chatKey]) || !is_array($history['chats'][$chatKey])) {
        return;
    }

    $history['chats'][$chatKey]['followups_stopped_at'] = date('c');
    $history['chats'][$chatKey]['followups_stopped_reason'] = $reason;
    writeJsonFile($file, $history);
}

function mergeChatContactData(array $context, array $contact): array
{
    $file = (string) config('CHAT_HISTORY_FILE');
    $history = readJsonFile($file, ['chats' => []]);
    $key = chatHistoryKey($context);

    if (!isset($history['chats'][$key]) || !is_array($history['chats'][$key])) {
        $history['chats'][$key] = [
            'context' => $context,
            'messages' => [],
        ];
    }

    $stored = (array) ($history['chats'][$key]['contact'] ?? []);
    $receivedAt = (array) ($history['chats'][$key]['contact_received_at'] ?? []);
    foreach (['phone', 'city', 'full_name', 'interest_group', 'branch'] as $field) {
        $value = trim((string) ($contact[$field] ?? ''));
        if ($value !== '') {
            if (trim((string) ($stored[$field] ?? '')) !== $value
                || trim((string) ($receivedAt[$field] ?? '')) === ''
            ) {
                $receivedAt[$field] = date('c');
            }
            $stored[$field] = $value;
        }
    }

    $stored += [
        'phone' => '',
        'city' => '',
        'full_name' => '',
        'interest_group' => '',
        'branch' => '',
    ];

    $history['chats'][$key]['contact'] = $stored;
    $history['chats'][$key]['contact_received_at'] = $receivedAt;
    $history['chats'][$key]['context'] = array_filter($context, static fn ($value): bool => $value !== null && $value !== '');
    $history['chats'][$key]['updated_at'] = date('c');

    writeJsonFile($file, $history);

    return $stored;
}

function markPhoneOnlyEndOfDayProcessed(string $chatKey, string $dealId, string $phone, array $crmResult): void
{
    $file = (string) config('CHAT_HISTORY_FILE');
    $history = readJsonFile($file, ['chats' => []]);

    if (!isset($history['chats'][$chatKey]) || !is_array($history['chats'][$chatKey])) {
        return;
    }

    $history['chats'][$chatKey]['phone_only_end_of_day'] = [
        'processed_at' => date('c'),
        'deal_id' => $dealId,
        'phone' => $phone,
        'result' => $crmResult,
    ];

    writeJsonFile($file, $history);
}

function getChatContactData(array $context): array
{
    $history = readJsonFile((string) config('CHAT_HISTORY_FILE'), ['chats' => []]);
    $key = chatHistoryKey($context);
    $contact = (array) ($history['chats'][$key]['contact'] ?? []);

    return [
        'phone' => trim((string) ($contact['phone'] ?? '')),
        'city' => trim((string) ($contact['city'] ?? '')),
        'full_name' => trim((string) ($contact['full_name'] ?? '')),
        'interest_group' => normalizeInterestGroup($contact['interest_group'] ?? ''),
        'branch' => normalizeBranchName($contact['branch'] ?? ''),
    ];
}

function normalizeBranchName($value): string
{
    $value = trim((string) $value);
    if ($value === '') {
        return '';
    }

    $value = function_exists('mb_strtolower')
        ? mb_strtolower($value, 'UTF-8')
        : strtolower($value);
    $value = strtr($value, [
        'А' => 'а', 'Б' => 'б', 'В' => 'в', 'Г' => 'г', 'Д' => 'д', 'Е' => 'е',
        'Ё' => 'ё', 'Ж' => 'ж', 'З' => 'з', 'И' => 'и', 'Й' => 'й', 'К' => 'к',
        'Л' => 'л', 'М' => 'м', 'Н' => 'н', 'О' => 'о', 'П' => 'п', 'Р' => 'р',
        'С' => 'с', 'Т' => 'т', 'У' => 'у', 'Ф' => 'ф', 'Х' => 'х', 'Ц' => 'ц',
        'Ч' => 'ч', 'Ш' => 'ш', 'Щ' => 'щ', 'Ъ' => 'ъ', 'Ы' => 'ы', 'Ь' => 'ь',
        'Э' => 'э', 'Ю' => 'ю', 'Я' => 'я',
    ]);
    $value = str_replace(['ё', '-', '_', '.', ','], ['е', ' ', ' ', ' ', ' '], $value);
    $value = preg_replace('/\s+/u', ' ', $value) ?? $value;
    $value = trim($value);

    $branches = [
        'казань' => 'Казань',
        'самара' => 'Самара',
        'саратов' => 'Саратов',
        'екатеринбург' => 'Екатеринбург',
        'уфа' => 'Уфа',
        'нижний новгород' => 'Нижний Новгород',
        'воронеж' => 'Воронеж',
        'ростов на дону' => 'Ростов на Дону',
        'москва' => 'Москва',
        'пермь' => 'Пермь',
        'челябинск' => 'Челябинск',
        'краснодар' => 'Краснодар',
        'санкт петербург' => 'Санкт-Петербург',
    ];

    return $branches[$value] ?? '';
}

function normalizeInterestGroup($value): string
{
    $value = trim((string) $value);
    if ($value === '') {
        return '';
    }

    $value = function_exists('mb_strtolower')
        ? mb_strtolower($value, 'UTF-8')
        : strtolower($value);

    return in_array($value, ['техника', 'запчасти', 'сервис', 'другое'], true) ? $value : '';
}

function isContactDataComplete(array $contact): bool
{
    return trim((string) ($contact['phone'] ?? '')) !== ''
        && trim((string) ($contact['city'] ?? '')) !== '';
}

function markChatAwaitingClientReply(array $context): void
{
    $file = (string) config('CHAT_HISTORY_FILE');
    $history = readJsonFile($file, ['chats' => []]);
    $key = chatHistoryKey($context);

    if (!isset($history['chats'][$key]) || !is_array($history['chats'][$key])) {
        $history['chats'][$key] = [
            'context' => $context,
            'messages' => [],
        ];
    }

    $history['chats'][$key]['context'] = array_filter($context, static fn ($value): bool => $value !== null && $value !== '');
    if (trim((string) ($history['chats'][$key]['followup_started_at'] ?? '')) === '') {
        $history['chats'][$key]['followup_started_at'] = date('c');
    }

    if (!isset($history['chats'][$key]['followups']) || !is_array($history['chats'][$key]['followups'])) {
        $history['chats'][$key]['followups'] = [
            'sent' => [],
        ];
    }

    writeJsonFile($file, $history);
}

function clearChatAwaitingClientReply(array $context): void
{
    $file = (string) config('CHAT_HISTORY_FILE');
    $history = readJsonFile($file, ['chats' => []]);
    $key = chatHistoryKey($context);

    if (!isset($history['chats'][$key]) || !is_array($history['chats'][$key])) {
        return;
    }

    unset($history['chats'][$key]['followup_started_at']);
    unset($history['chats'][$key]['followups']);
    unset($history['chats'][$key]['followup_sent_at']);
    unset($history['chats'][$key]['followup_for_message_at']);
    unset($history['chats'][$key]['no_response_marked_at']);

    writeJsonFile($file, $history);
}

function clearChatHistory(?string $dialogId = null, ?string $chatId = null): array
{
    $file = (string) config('CHAT_HISTORY_FILE');
    $history = readJsonFile($file, ['chats' => []]);

    if ($dialogId === null && $chatId === null) {
        writeJsonFile($file, ['chats' => []]);

        return ['cleared' => 'all'];
    }

    $context = [];
    if ($dialogId !== null && $dialogId !== '') {
        $context['dialog_id'] = $dialogId;
    }
    if ($chatId !== null && $chatId !== '') {
        $context['chat_id'] = $chatId;
    }

    $key = chatHistoryKey($context);
    unset($history['chats'][$key]);
    writeJsonFile($file, $history);

    return ['cleared' => $key];
}

function listChatHistories(): array
{
    return readJsonFile((string) config('CHAT_HISTORY_FILE'), ['chats' => []]);
}

function markChatFollowupSent(string $chatKey, int $stageIndex, string $message): void
{
    $file = (string) config('CHAT_HISTORY_FILE');
    $history = readJsonFile($file, ['chats' => []]);

    if (!isset($history['chats'][$chatKey]) || !is_array($history['chats'][$chatKey])) {
        return;
    }

    if (!isset($history['chats'][$chatKey]['followups']) || !is_array($history['chats'][$chatKey]['followups'])) {
        $history['chats'][$chatKey]['followups'] = [
            'sent' => [],
        ];
    }

    $history['chats'][$chatKey]['followup_sent_at'] = date('c');
    $history['chats'][$chatKey]['followups']['sent'][(string) $stageIndex] = [
        'sent_at' => date('c'),
        'message' => $message,
    ];

    writeJsonFile($file, $history);
}

function markChatNoResponseMarked(string $chatKey, array $crmResult): void
{
    $file = (string) config('CHAT_HISTORY_FILE');
    $history = readJsonFile($file, ['chats' => []]);

    if (!isset($history['chats'][$chatKey]) || !is_array($history['chats'][$chatKey])) {
        return;
    }

    $history['chats'][$chatKey]['no_response_marked_at'] = date('c');
    $history['chats'][$chatKey]['no_response_crm_result'] = $crmResult;

    writeJsonFile($file, $history);
}

function hasPhoneWorkflowStarted(array $context, string $phone): bool
{
    $phone = trim($phone);
    if ($phone === '') {
        return false;
    }

    $history = readJsonFile((string) config('CHAT_HISTORY_FILE'), ['chats' => []]);
    $key = chatHistoryKey($context);
    $workflow = (array) ($history['chats'][$key]['phone_workflow'] ?? []);

    return trim((string) ($workflow['phone'] ?? '')) === $phone
        && trim((string) ($workflow['started_at'] ?? '')) !== '';
}

function markPhoneWorkflowStarted(array $context, string $phone, array $workflowResult): void
{
    $phone = trim($phone);
    if ($phone === '') {
        return;
    }

    $file = (string) config('CHAT_HISTORY_FILE');
    $history = readJsonFile($file, ['chats' => []]);
    $key = chatHistoryKey($context);

    if (!isset($history['chats'][$key]) || !is_array($history['chats'][$key])) {
        $history['chats'][$key] = [
            'context' => $context,
            'messages' => [],
        ];
    }

    $history['chats'][$key]['phone_workflow'] = [
        'phone' => $phone,
        'started_at' => date('c'),
        'result' => $workflowResult,
    ];

    writeJsonFile($file, $history);
}

function getQualificationWorkflowState(array $context): array
{
    $history = readJsonFile((string) config('CHAT_HISTORY_FILE'), ['chats' => []]);
    $key = chatHistoryKey($context);

    return (array) ($history['chats'][$key]['qualification_distribution_workflow'] ?? []);
}

function markQualificationWorkflowPending(
    array $context,
    string $dealId,
    array $workflowResult
): void {
    $file = (string) config('CHAT_HISTORY_FILE');
    $history = readJsonFile($file, ['chats' => []]);
    $key = chatHistoryKey($context);

    if (!isset($history['chats'][$key]) || !is_array($history['chats'][$key])) {
        $history['chats'][$key] = [
            'context' => $context,
            'messages' => [],
        ];
    }

    $previous = (array) ($history['chats'][$key]['qualification_distribution_workflow'] ?? []);
    $history['chats'][$key]['qualification_distribution_workflow'] = [
        'status' => 'pending',
        'deal_id' => $dealId,
        'first_failed_at' => (string) ($previous['first_failed_at'] ?? date('c')),
        'last_attempt_at' => date('c'),
        'attempts' => max(0, (int) ($previous['attempts'] ?? 0)) + 1,
        'result' => $workflowResult,
    ];

    writeJsonFile($file, $history);
}

function markQualificationWorkflowStarted(
    array $context,
    string $dealId,
    array $workflowResult
): void {
    $file = (string) config('CHAT_HISTORY_FILE');
    $history = readJsonFile($file, ['chats' => []]);
    $key = chatHistoryKey($context);

    if (!isset($history['chats'][$key]) || !is_array($history['chats'][$key])) {
        $history['chats'][$key] = [
            'context' => $context,
            'messages' => [],
        ];
    }

    $previous = (array) ($history['chats'][$key]['qualification_distribution_workflow'] ?? []);
    $history['chats'][$key]['qualification_distribution_workflow'] = [
        'status' => 'started',
        'deal_id' => $dealId,
        'started_at' => date('c'),
        'attempts' => max(0, (int) ($previous['attempts'] ?? 0)) + 1,
        'result' => $workflowResult,
    ];

    writeJsonFile($file, $history);
}
