<?php
namespace Espo\Custom\Services;

use Espo\Services\Record;
use Espo\ORM\Entity;
use Espo\Core\Exceptions\{Forbidden, NotFound, BadRequest};
use Espo\Core\FileStorage\Manager as FileStorageManager;
use Espo\Core\Utils\File\Manager as FileManager;

/**
 * Service: CDokumente
 */
class CDokumente extends Record
{
    /**
     * Get FileStorageManager from container on-demand
     */
    private function getFileStorageManager(): FileStorageManager
    {
        return $this->injectableFactory->create(FileStorageManager::class);
    }
    
    /**
     * Get FileManager from container on-demand
     */
    private function getFileManager(): FileManager
    {
        return $this->injectableFactory->create(FileManager::class);
    }
    
    /**
     * Duplicate a document entity including its attachment file
     * 
     * This creates a complete copy of a document with:
     * - All entity fields (name, description, etc.)
     * - Physical attachment file copied to new location
     * - Recalculated blake3hash
     * - Reset fileStatus to 'new'
     * 
     * @param string $documentId Source document ID to duplicate
     * @return Entity New CDokumente entity
     * @throws NotFound If document doesn't exist
     * @throws Forbidden If no read access
     * @throws BadRequest If document has no attachment
     */
    public function duplicateDocument(string $documentId): Entity
    {
        // 1. Load source document
        $sourceDoc = $this->entityManager->getEntity('CDokumente', $documentId);
        if (!$sourceDoc) {
            throw new NotFound('Document not found');
        }
        
        // 2. ACL Check
        if (!$this->acl->check($sourceDoc, 'read')) {
            throw new Forbidden('No read access to document');
        }
        
        // 3. Get source attachment
        $sourceAttachmentId = $sourceDoc->get('dokumentId');
        if (!$sourceAttachmentId) {
            throw new BadRequest('Document has no attachment');
        }
        
        $sourceAttachment = $this->entityManager->getEntity('Attachment', $sourceAttachmentId);
        if (!$sourceAttachment) {
            throw new BadRequest('Source attachment not found');
        }
        
        try {
            // 4. Copy attachment file physically
            $newAttachment = $this->duplicateAttachment($sourceAttachment);
            
            // 5. Create new document entity
            $newDoc = $this->entityManager->getEntity('CDokumente');
            
            // Copy all relevant fields
            $newDoc->set([
                'name' => $sourceDoc->get('name'),
                'description' => $sourceDoc->get('description'),
                'dokumentId' => $newAttachment->getId(),
                'assignedUserId' => $sourceDoc->get('assignedUserId'),
                'fileStatus' => 'new' // Reset to 'new'
            ]);
            
            // Copy teams
            $teamsIds = $sourceDoc->getLinkMultipleIdList('teams');
            if (!empty($teamsIds)) {
                $newDoc->setLinkMultipleIdList('teams', $teamsIds);
            }
            
            // Copy preview if exists
            if ($sourceDoc->get('previewId')) {
                $sourcePreview = $this->entityManager->getEntity('Attachment', $sourceDoc->get('previewId'));
                if ($sourcePreview) {
                    $newPreview = $this->duplicateAttachment($sourcePreview);
                    $newDoc->set('previewId', $newPreview->getId());
                }
            }
            
            // 6. Save new document (this will trigger blake3hash calculation via Hook)
            $this->entityManager->saveEntity($newDoc);
            
            // 7. Return new document
            return $newDoc;
            
        } catch (\Exception $e) {
            $GLOBALS['log']->error('CDokumente duplicateDocument Error: ' . $e->getMessage());
            throw new \RuntimeException('Failed to duplicate document: ' . $e->getMessage());
        }
    }
    
    /**
     * Duplicate an attachment entity including physical file
     * 
     * @param Entity $sourceAttachment Source attachment to duplicate
     * @return Entity New attachment entity
     */
    private function duplicateAttachment(Entity $sourceAttachment): Entity
    {
        // 1. Get source file path
        $sourceFilePath = $this->getFileStorageManager()->getLocalFilePath($sourceAttachment);
        
        if (!file_exists($sourceFilePath)) {
            throw new \RuntimeException('Source file not found: ' . $sourceFilePath);
        }
        
        // 2. Read source file content
        $fileContent = $this->getFileManager()->getContents($sourceFilePath);
        
        // 3. Create new attachment entity
        $newAttachment = $this->entityManager->getEntity('Attachment');
        $newAttachment->set([
            'name' => $sourceAttachment->get('name'),
            'type' => $sourceAttachment->get('type'),
            'size' => $sourceAttachment->get('size'),
            'role' => $sourceAttachment->get('role') ?? 'Attachment',
            'storageFilePath' => null // Will be set by putContents
        ]);
        
        $this->entityManager->saveEntity($newAttachment);
        
        // 4. Write file content to new location
        $this->getFileStorageManager()->putContents($newAttachment, $fileContent);
        
        // 5. Return new attachment
        return $newAttachment;
    }
}
