<?php

namespace Espo\Modules\SmartAssistant\Services;

use Espo\ORM\EntityManager;
use Espo\Entities\User;
use Espo\Core\Utils\Log;

class ConversationRepository
{
    private EntityManager $entityManager;
    private User $user;
    private Log $log;

    public function __construct(EntityManager $entityManager, User $user, Log $log)
    {
        $this->entityManager = $entityManager;
        $this->user = $user;
        $this->log = $log;
    }

    public function startOrResume(string $type, ?string $conversationKey = null, ?string $caseId = null): array
    {
        if ($conversationKey) {
            $entity = $this->entityManager->getRDBRepository('AssistantConversation')
                ->where(['conversationKey' => $conversationKey, 'deleted' => false])->findOne();
            if ($entity) return ['id' => $entity->get('id'), 'conversationKey' => $conversationKey];
        }

        $conversationKey = $conversationKey ?: uniqid($type === 'office' ? 'oconv_' : 'conv_', true);
        $entity = $this->entityManager->getNewEntity('AssistantConversation');
        $entity->set([
            'name' => $type === 'office' ? 'שיחה עם העוזר החכם' : 'שיחה עם העוזר',
            'conversationType' => $type, 'status' => 'Active',
            'conversationKey' => $conversationKey,
            'assignedUserId' => $this->user->getId(),
            'messageCount' => 0, 'messagesData' => [],
            'lastMessageAt' => date('Y-m-d H:i:s'),
        ]);
        if ($caseId && $type === 'case') $entity->set('caseId', $caseId);
        $this->entityManager->saveEntity($entity);

        return ['id' => $entity->get('id'), 'conversationKey' => $conversationKey];
    }

    public function appendMessage(string $conversationKey, string $role, string $content, array $actions = []): void
    {
        $entity = $this->entityManager->getRDBRepository('AssistantConversation')
            ->where(['conversationKey' => $conversationKey, 'deleted' => false])->findOne();

        if (!$entity) {
            $this->startOrResume('office', $conversationKey);
            $entity = $this->entityManager->getRDBRepository('AssistantConversation')
                ->where(['conversationKey' => $conversationKey, 'deleted' => false])->findOne();
            if (!$entity) return;
        }

        $messages = json_decode(json_encode($entity->get('messagesData') ?? []), true);

        $newMessage = ['role' => $role, 'content' => $content, 'timestamp' => date('Y-m-d H:i:s')];
        if (!empty($actions)) $newMessage['actions'] = $actions;
        $messages[] = $newMessage;

        if ($role === 'user' && $entity->get('messageCount') === 0) {
            $title = mb_substr($content, 0, 100);
            if (mb_strlen($content) > 100) $title .= '...';
            $entity->set('name', $title);
        }

        $entity->set([
            'messagesData' => $messages, 'messageCount' => count($messages),
            'lastMessageAt' => date('Y-m-d H:i:s'),
            'lastMessagePreview' => mb_substr($content, 0, 200),
        ]);
        $this->entityManager->saveEntity($entity);
    }

    public function getMessages(string $conversationKey): array
    {
        $entity = $this->entityManager->getRDBRepository('AssistantConversation')
            ->where(['conversationKey' => $conversationKey, 'deleted' => false])->findOne();
        if (!$entity) return [];
        return json_decode(json_encode($entity->get('messagesData') ?? []), true);
    }

    public function getRecentConversations(?string $type = null, ?string $caseId = null, int $limit = 20): array
    {
        $where = ['assignedUserId' => $this->user->getId(), 'deleted' => false];
        if ($type) $where['conversationType'] = $type;
        if ($caseId) $where['caseId'] = $caseId;

        $result = [];
        foreach ($this->entityManager->getRDBRepository('AssistantConversation')
            ->select(['id', 'name', 'conversationType', 'conversationKey', 'status', 'messageCount', 'lastMessageAt', 'lastMessagePreview', 'caseId', 'caseName'])
            ->where($where)->order('lastMessageAt', 'DESC')->limit(0, $limit)->find() as $conv) {
            $result[] = [
                'id' => $conv->get('id'), 'name' => $conv->get('name'),
                'conversationType' => $conv->get('conversationType'),
                'conversationKey' => $conv->get('conversationKey'),
                'status' => $conv->get('status'), 'messageCount' => $conv->get('messageCount'),
                'lastMessageAt' => $conv->get('lastMessageAt'),
                'lastMessagePreview' => $conv->get('lastMessagePreview'),
                'caseId' => $conv->get('caseId'), 'caseName' => $conv->get('caseName'),
            ];
        }
        return $result;
    }

    public function searchConversations(string $query, ?string $type = null, int $limit = 20): array
    {
        $where = ['deleted' => false, 'OR' => [['name*' => "%{$query}%"], ['lastMessagePreview*' => "%{$query}%"]]];
        if ($type) $where['conversationType'] = $type;

        $result = [];
        foreach ($this->entityManager->getRDBRepository('AssistantConversation')
            ->select(['id', 'name', 'conversationType', 'conversationKey', 'messageCount', 'lastMessageAt', 'lastMessagePreview', 'caseId', 'caseName', 'assignedUserName'])
            ->where($where)->order('lastMessageAt', 'DESC')->limit(0, $limit)->find() as $conv) {
            $result[] = [
                'id' => $conv->get('id'), 'name' => $conv->get('name'),
                'conversationType' => $conv->get('conversationType'),
                'conversationKey' => $conv->get('conversationKey'),
                'messageCount' => $conv->get('messageCount'),
                'lastMessageAt' => $conv->get('lastMessageAt'),
                'lastMessagePreview' => $conv->get('lastMessagePreview'),
                'caseId' => $conv->get('caseId'), 'caseName' => $conv->get('caseName'),
                'assignedUser' => $conv->get('assignedUserName'),
            ];
        }
        return $result;
    }

    public function storePendingActions(string $conversationKey, string $caseId, string $userId, array $actions): void
    {
        $entity = $this->entityManager->getRDBRepository('AssistantConversation')
            ->where(['conversationKey' => $conversationKey, 'deleted' => false])->findOne();
        if (!$entity) return;

        $data = json_decode(json_encode($entity->get('messagesData') ?? []), true);
        for ($i = count($data) - 1; $i >= 0; $i--) {
            if (($data[$i]['role'] ?? '') === 'assistant') { $data[$i]['pendingActions'] = $actions; break; }
        }
        $entity->set('messagesData', $data);
        $this->entityManager->saveEntity($entity);

        $dir = 'data/tmp/assistant-conversations';
        if (!is_dir($dir)) mkdir($dir, 0755, true);
        file_put_contents($dir . '/' . $conversationKey . '.json', json_encode([
            'caseId' => $caseId, 'userId' => $userId, 'actions' => $actions, 'createdAt' => date('Y-m-d H:i:s'),
        ]));
    }
}
