<?php

namespace Espo\Modules\SmartAssistant\Services;

use Espo\Core\InjectableFactory;
use Espo\Core\Utils\Log;
use Espo\ORM\EntityManager;

class CaseContextBuilder
{
    private EntityManager $entityManager;
    private InjectableFactory $injectableFactory;
    private Log $log;

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

    public function buildContext(string $caseId, string $userId): array
    {
        $case = $this->entityManager->getEntityById('Case', $caseId);
        if (!$case) return ['error' => 'Case not found'];

        return [
            'case' => $this->getCaseData($case),
            'contacts' => $this->getCaseContacts($case),
            'openTasks' => $this->getOpenTasks($caseId),
            'upcomingMeetings' => $this->getUpcomingMeetings($caseId),
            'recentCalls' => $this->getRecentCalls($caseId),
            'recentNotes' => $this->getRecentNotes($caseId),
            'availableTemplates' => $this->getAvailableTemplates(),
            'documents' => $this->getDocumentListing($caseId),
            'currentUser' => $this->getUserData($userId),
            'validStatuses' => ActionExecutor::VALID_STATUSES,
        ];
    }

    private function getCaseData($case): array
    {
        return [
            'id' => $case->get('id'),
            'name' => $case->get('name'),
            'number' => $case->get('number'),
            'status' => $case->get('status'),
            'type' => $case->get('type'),
            'description' => $case->get('description'),
            'cCourt' => $case->get('cCourt'),
            'cCourtCaseNumber' => $case->get('cCourtCaseNumber'),
            'cJudge' => $case->get('cJudge'),
            'cJudgeTitle' => $case->get('cJudgeTitle'),
            'cNextHearing' => $case->get('cNextHearing'),
            'cFilingDate' => $case->get('cFilingDate'),
            'cLegalAidNumber' => $case->get('cLegalAidNumber'),
            'cLegalAidStatus' => $case->get('cLegalAidStatus'),
            'assignedUserName' => $case->get('assignedUserName'),
            'assignedUserId' => $case->get('assignedUserId'),
            'accountName' => $case->get('accountName'),
            'accountId' => $case->get('accountId'),
        ];
    }

    private function getCaseContacts($case): array
    {
        $contacts = [];
        $collection = $this->entityManager->getRDBRepository('Case')
            ->getRelation($case, 'contacts')->limit(0, 20)->find();

        foreach ($collection as $c) {
            $contacts[] = [
                'id' => $c->get('id'),
                'name' => $c->get('name'),
                'role' => $c->get('contactRole') ?? '',
                'phoneNumber' => $c->get('phoneNumber'),
                'emailAddress' => $c->get('emailAddress'),
            ];
        }
        return $contacts;
    }

    private function getOpenTasks(string $caseId): array
    {
        $tasks = [];
        $collection = $this->entityManager->getRDBRepository('Task')
            ->where(['parentType' => 'Case', 'parentId' => $caseId, 'status!=' => ['Completed', 'Canceled']])
            ->order('dateEnd', 'ASC')->limit(0, 10)->find();

        foreach ($collection as $t) {
            $tasks[] = [
                'id' => $t->get('id'), 'name' => $t->get('name'), 'status' => $t->get('status'),
                'dateEnd' => $t->get('dateEnd'), 'priority' => $t->get('priority'),
                'assignedUserName' => $t->get('assignedUserName'),
            ];
        }
        return $tasks;
    }

    private function getUpcomingMeetings(string $caseId): array
    {
        $meetings = [];
        $collection = $this->entityManager->getRDBRepository('Meeting')
            ->where(['parentType' => 'Case', 'parentId' => $caseId, 'status' => 'Planned', 'dateStart>=' => date('Y-m-d H:i:s')])
            ->order('dateStart', 'ASC')->limit(0, 5)->find();

        foreach ($collection as $m) {
            $meetings[] = [
                'id' => $m->get('id'), 'name' => $m->get('name'),
                'dateStart' => $m->get('dateStart'), 'dateEnd' => $m->get('dateEnd'),
                'description' => $m->get('description'),
            ];
        }
        return $meetings;
    }

    private function getRecentCalls(string $caseId): array
    {
        $calls = [];
        $collection = $this->entityManager->getRDBRepository('Call')
            ->where(['parentType' => 'Case', 'parentId' => $caseId])
            ->order('dateStart', 'DESC')->limit(0, 10)->find();

        foreach ($collection as $c) {
            $calls[] = [
                'id' => $c->get('id'), 'name' => $c->get('name'),
                'status' => $c->get('status'), 'direction' => $c->get('direction'),
                'dateStart' => $c->get('dateStart'), 'dateEnd' => $c->get('dateEnd'),
                'description' => $c->get('description'),
            ];
        }
        return $calls;
    }

    private function getRecentNotes(string $caseId): array
    {
        $notes = [];
        $collection = $this->entityManager->getRDBRepository('Note')
            ->where(['parentType' => 'Case', 'parentId' => $caseId, 'type' => 'Post'])
            ->order('createdAt', 'DESC')->limit(0, 10)->find();

        foreach ($collection as $n) {
            $notes[] = [
                'post' => $n->get('post'), 'createdAt' => $n->get('createdAt'),
                'createdByName' => $n->get('createdByName'),
            ];
        }
        return $notes;
    }

    private function getAvailableTemplates(): array
    {
        $templates = [];
        $collection = $this->entityManager->getRDBRepository('DocumentTemplate')
            ->where(['entityType' => 'Case'])->order('name', 'ASC')->find();

        foreach ($collection as $t) {
            $templates[] = ['id' => $t->get('id'), 'name' => $t->get('name')];
        }
        return $templates;
    }

    private function getUserData(string $userId): array
    {
        $user = $this->entityManager->getEntityById('User', $userId);
        if (!$user) return ['id' => $userId, 'name' => 'Unknown'];
        return ['id' => $user->get('id'), 'name' => $user->get('name')];
    }

    private function getDocumentListing(string $caseId): array
    {
        try {
            $analyzer = $this->injectableFactory->create(DocumentAnalyzer::class);
            $result = $analyzer->listDocumentsRecursive($caseId);

            $simplified = ['totalFiles' => $result['totalFiles'], 'folders' => [], 'rootFiles' => []];

            foreach ($result['folders'] as $folder) {
                $files = [];
                foreach ($folder['files'] as $file) {
                    $files[] = ['name' => $file['name'], 'size' => $file['size'], 'mimeType' => $file['mimeType'], 'path' => $file['path']];
                }
                $simplified['folders'][] = ['name' => $folder['name'], 'fileCount' => count($files), 'files' => $files];
            }

            foreach ($result['rootFiles'] as $file) {
                $simplified['rootFiles'][] = ['name' => $file['name'], 'size' => $file['size'], 'mimeType' => $file['mimeType'], 'path' => $file['path']];
            }

            return $simplified;
        } catch (\Exception $e) {
            $this->log->debug("SmartAssistant: Document listing unavailable: " . $e->getMessage());
            return [];
        }
    }
}
