<?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);

    $restoredFromOperationalState = false;
    if (!isset($history['chats'][$key]) || !is_array($history['chats'][$key])) {
        $operationalState = readChatFollowupOperationalState($key);
        $restoredFromOperationalState = $operationalState !== [];
        $history['chats'][$key] = $restoredFromOperationalState
            ? $operationalState
            : ['context' => $context, 'messages' => []];
        if ($role === 'user' && $restoredFromOperationalState) {
            $history['chats'][$key]['messages'] = [];
            unset($history['chats'][$key]['contact']);
            unset($history['chats'][$key]['contact_received_at']);
        }
    }

    $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);
    saveChatFollowupOperationalState($key, $history['chats'][$key]);
}

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

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

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] = readChatFollowupOperationalState($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);
    saveChatFollowupOperationalState($key, $history['chats'][$key]);

    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 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] = readChatFollowupOperationalState($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);
    saveChatFollowupOperationalState($key, $history['chats'][$key]);
}

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

    $chat = $history['chats'][$key] ?? readChatFollowupOperationalState($key);
    if (!is_array($chat) || $chat === []) {
        return;
    }

    unset($chat['followup_started_at']);
    unset($chat['followups']);
    unset($chat['followup_sent_at']);
    unset($chat['followup_for_message_at']);
    unset($chat['no_response_marked_at']);

    if (isset($history['chats'][$key])) {
        $history['chats'][$key] = $chat;
        writeJsonFile($file, $history);
    }
    saveChatFollowupOperationalState($key, $chat);
}

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 listChatHistoriesForFollowups(): array
{
    $history = listChatHistories();
    if (!isset($history['chats']) || !is_array($history['chats'])) {
        $history['chats'] = [];
    }

    $pattern = followupOperationalStateDirectory() . '/*.json';
    foreach (glob($pattern) ?: [] as $path) {
        $stored = readJsonFile($path, []);
        $chatKey = trim((string) ($stored['chat_key'] ?? ''));
        $chat = (array) ($stored['chat'] ?? []);
        if ($chatKey === '' || $chat === [] || isset($history['chats'][$chatKey])) {
            continue;
        }

        $history['chats'][$chatKey] = $chat;
    }

    return $history;
}

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

    $chat = $history['chats'][$chatKey] ?? readChatFollowupOperationalState($chatKey);
    if (!is_array($chat) || $chat === []) {
        return;
    }

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

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

    if (isset($history['chats'][$chatKey])) {
        $history['chats'][$chatKey] = $chat;
        writeJsonFile($file, $history);
    }
    saveChatFollowupOperationalState($chatKey, $chat);
}

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

    $chat = $history['chats'][$chatKey] ?? readChatFollowupOperationalState($chatKey);
    if (!is_array($chat) || $chat === []) {
        return;
    }

    $chat['no_response_marked_at'] = date('c');
    $chat['no_response_crm_result'] = $crmResult;

    if (isset($history['chats'][$chatKey])) {
        $history['chats'][$chatKey] = $chat;
        writeJsonFile($file, $history);
    }
    saveChatFollowupOperationalState($chatKey, $chat);
}

function saveChatFollowupOperationalState(string $chatKey, array $chat): void
{
    $chatKey = trim($chatKey);
    if ($chatKey === '') {
        return;
    }

    $messages = (array) ($chat['messages'] ?? []);
    $lastMessage = $messages !== [] ? end($messages) : null;
    $snapshot = [
        'context' => (array) ($chat['context'] ?? []),
        'contact' => (array) ($chat['contact'] ?? []),
        'contact_received_at' => (array) ($chat['contact_received_at'] ?? []),
        'messages' => is_array($lastMessage) ? [$lastMessage] : [],
    ];

    foreach ([
        'updated_at',
        'followup_started_at',
        'followup_sent_at',
        'followup_for_message_at',
        'followups',
        'followups_stopped_at',
        'followups_stopped_reason',
        'no_response_marked_at',
        'no_response_crm_result',
    ] as $field) {
        if (array_key_exists($field, $chat)) {
            $snapshot[$field] = $chat[$field];
        }
    }

    writeJsonFile(followupOperationalStateFile($chatKey), [
        'chat_key' => $chatKey,
        'saved_at' => date('c'),
        'chat' => $snapshot,
    ]);
}

function readChatFollowupOperationalState(string $chatKey): array
{
    $stored = readJsonFile(followupOperationalStateFile($chatKey), []);

    return (array) ($stored['chat'] ?? []);
}

function followupOperationalStateFile(string $chatKey): string
{
    return followupOperationalStateDirectory() . '/' . sha1($chatKey) . '.json';
}

function followupOperationalStateDirectory(): string
{
    return dirname((string) config('CHAT_HISTORY_FILE')) . '/followup_states';
}

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, string $dealId = ''): array
{
    $dealId = trim($dealId);
    if ($dealId !== '') {
        $dealWorkflow = readJsonFile(qualificationWorkflowStateFile($dealId), []);
        if ($dealWorkflow !== []) {
            return (array) $dealWorkflow;
        }
    }

    $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'] ?? []);
    $workflowState = [
        '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,
    ];
    $history['chats'][$key]['qualification_distribution_workflow'] = $workflowState;

    writeJsonFile($file, $history);
    saveDealQualificationWorkflowState($dealId, $workflowState);
}

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'] ?? []);
    $workflowState = [
        'status' => 'started',
        'deal_id' => $dealId,
        'started_at' => date('c'),
        'attempts' => max(0, (int) ($previous['attempts'] ?? 0)) + 1,
        'result' => $workflowResult,
    ];
    $history['chats'][$key]['qualification_distribution_workflow'] = $workflowState;

    writeJsonFile($file, $history);
    saveDealQualificationWorkflowState($dealId, $workflowState);
}

function saveDealQualificationWorkflowState(string $dealId, array $workflowState): void
{
    $dealId = trim($dealId);
    if ($dealId === '') {
        return;
    }

    writeJsonFile(qualificationWorkflowStateFile($dealId), $workflowState);
}

function qualificationWorkflowStateFile(string $dealId): string
{
    $storageDir = dirname((string) config('CHAT_HISTORY_FILE'));

    return $storageDir . '/qualification_workflows/deal_' . trim($dealId) . '.json';
}
