<?php
namespace Espo\Custom\Hooks\CMietinkasso;

use Espo\ORM\Entity;
use Espo\Core\Hook\Hook\AfterRelate;
use Espo\Core\Hook\Hook\AfterUnrelate;

/**
 * Hook: Propagiert Dokumenten-Verknüpfungen von Mietinkasso zu AdvowareAkten und AIKnowledge
 * 
 * - Wenn Dokument mit Mietinkasso verknüpft wird → verknüpfe auch mit AdvowareAkten + AIKnowledge
 * - Wenn Dokument von Mietinkasso entknüpft wird → entknüpfe auch von AdvowareAkten + AIKnowledge
 */
class PropagateDocuments implements AfterRelate, AfterUnrelate
{
    private static array $processing = [];
    
    public function __construct(
        private \Espo\ORM\EntityManager $entityManager
    ) {}
    
    public function afterRelate(
        Entity $entity,
        string $relationName,
        Entity $foreignEntity,
        array $columnData,
        \Espo\ORM\Repository\Option\RelateOptions $options
    ): void {
        // Nur für dokumentesmietinkasso-Beziehung
        if ($relationName !== 'dokumentesmietinkasso') {
            return;
        }
        
        // Vermeide Loops
        $key = $entity->getId() . '-' . $foreignEntity->getId() . '-relate';
        if (isset(self::$processing[$key])) {
            return;
        }
        self::$processing[$key] = true;
        
        try {
            // Hole verbundene AdvowareAkten
            $advowareAkten = $this->entityManager
                ->getRDBRepository('CMietinkasso')
                ->getRelation($entity, 'advowareAkten')
                ->findOne();
            
            // Set direct belongsTo relationship on document
            if ($advowareAkten) {
                $foreignEntity->set('cAktenId', $advowareAkten->getId());
                $foreignEntity->set('syncStatus', 'unclean');   // Advoware-Sync ausstehend
                $foreignEntity->set('aiSyncStatus', 'unclean'); // AI-Sync ausstehend
                $this->entityManager->saveEntity($foreignEntity, ['silent' => true, 'skipHooks' => true]);

                // Akte über neue Verlinkung informieren → syncStatus auf unclean
                $akte = $this->entityManager->getEntityById('CAkten', $advowareAkten->getId());
                if ($akte) {
                    $this->entityManager->saveEntity($akte, ['silent' => true]);
                }
            }
            
            // Hole verbundene AIKnowledge
            $aIKnowledge = $this->entityManager
                ->getRDBRepository('CMietinkasso')
                ->getRelation($entity, 'aIKnowledge')
                ->findOne();
            
            // Verknüpfe Dokument mit AIKnowledge
            if ($aIKnowledge) {
                $this->relateDocument($aIKnowledge, 'dokumentes', $foreignEntity);
            }
            
        } catch (\Exception $e) {
            $GLOBALS['log']->error('CMietinkasso PropagateDocuments (relate) Error: ' . $e->getMessage());
        } finally {
            unset(self::$processing[$key]);
        }
    }
    
    public function afterUnrelate(
        Entity $entity,
        string $relationName,
        Entity $foreignEntity,
        \Espo\ORM\Repository\Option\UnrelateOptions $options
    ): void {
        // Nur für dokumentesmietinkasso-Beziehung
        if ($relationName !== 'dokumentesmietinkasso') {
            return;
        }
        
        // Vermeide Loops
        $key = $entity->getId() . '-' . $foreignEntity->getId() . '-unrelate';
        if (isset(self::$processing[$key])) {
            return;
        }
        self::$processing[$key] = true;
        
        try {
            // Hole verbundene AdvowareAkten
            $advowareAkten = $this->entityManager
                ->getRDBRepository('CMietinkasso')
                ->getRelation($entity, 'advowareAkten')
                ->findOne();
            
            // Remove direct belongsTo relationship from document
            if ($advowareAkten && $foreignEntity->get('cAktenId') === $advowareAkten->getId()) {
                $akteId = $advowareAkten->getId(); // Vor dem Löschen merken
                $foreignEntity->set('cAktenId', null);
                $this->entityManager->saveEntity($foreignEntity, ['silent' => true, 'skipHooks' => true]);

                // Akte über Entlinkung informieren → syncStatus neu berechnen
                $akte = $this->entityManager->getEntityById('CAkten', $akteId);
                if ($akte) {
                    $this->entityManager->saveEntity($akte, ['silent' => true]);
                }
            }
            
            // Hole verbundene AIKnowledge
            $aIKnowledge = $this->entityManager
                ->getRDBRepository('CMietinkasso')
                ->getRelation($entity, 'aIKnowledge')
                ->findOne();
            
            // Entknüpfe Dokument von AIKnowledge
            if ($aIKnowledge) {
                $this->unrelateDocument($aIKnowledge, 'dokumentes', $foreignEntity);
            }
            
        } catch (\Exception $e) {
            $GLOBALS['log']->error('CMietinkasso PropagateDocuments (unrelate) Error: ' . $e->getMessage());
        } finally {
            unset(self::$processing[$key]);
        }
    }
    
    /**
     * Hilfsfunktion: Verknüpfe Dokument (nur wenn nicht bereits verknüpft)
     */
    private function relateDocument(Entity $parentEntity, string $relationName, Entity $document): void
    {
        $repository = $this->entityManager->getRDBRepository($parentEntity->getEntityType());
        $relation = $repository->getRelation($parentEntity, $relationName);
        
        // Prüfe ob bereits verknüpft
        $isRelated = $relation
            ->where(['id' => $document->getId()])
            ->findOne();
        
        if (!$isRelated) {
            $relation->relate($document);
        }
    }
    
    /**
     * Hilfsfunktion: Entknüpfe Dokument
     */
    private function unrelateDocument(Entity $parentEntity, string $relationName, Entity $document): void
    {
        $repository = $this->entityManager->getRDBRepository($parentEntity->getEntityType());
        $relation = $repository->getRelation($parentEntity, $relationName);
        
        // Prüfe ob verknüpft
        $isRelated = $relation
            ->where(['id' => $document->getId()])
            ->findOne();
        
        if ($isRelated) {
            $relation->unrelate($document);
        }
    }
}
