<?php

namespace App\EventSubscriber;

use App\Entity\File;
use App\Entity\FileAssociationNegotiationMessage;
use App\Entity\NegotiationMessage;
use App\Entity\Prospect;
use App\Event\NewEmailReceivedEvent;
use App\Service\FileService;
use App\Service\NegotiationMessageService;
use App\Service\NegotiationService;
use App\Service\ProspectService;
use League\Flysystem\Filesystem;
use PhpImap\IncomingMailAttachment;
use SplFileInfo;

final class EmailSubscriber
{
    private $negotiationService;
    /**
     * @var ProspectService
     */
    private $prospectService;
    /**
     * @var NegotiationMessageService
     */
    private $negotiationMessageService;
    /**
     * @var Filesystem
     */
    private $filesystem;
    /**
     * @var FileService
     */
    private $fileService;

    public function __construct(NegotiationService $negotiationService, ProspectService $prospectService, NegotiationMessageService $negotiationMessageService, Filesystem $filesystem, FileService $fileService)
    {
        $this->negotiationService = $negotiationService;
        $this->prospectService = $prospectService;
        $this->negotiationMessageService = $negotiationMessageService;
        $this->filesystem = $filesystem;
        $this->fileService = $fileService;
    }

    public function onCreate(NewEmailReceivedEvent $event)
    {
        $emailDTO = $event->getEmailDTO();

        try {
            $negotiation = $this->negotiationService->getByEmail($emailDTO->getTo());
        } catch (\Exception $e) {
            dump($e->getMessage(), $emailDTO);

            return;
        }

        $prospect = $negotiation->getProspect();
        if (!$prospect instanceof Prospect) {
            return;
        }

        $negotiationMessage = (new NegotiationMessage())
            ->setProspect($prospect)
            ->setNegotiation($negotiation)
            ->setDescription($emailDTO->getMessage())
            ->setDirection('INBOUND');

        if (count($emailDTO->getAttachments()) > 0) {
            $year = date('Y', time());
            $month = date('m', time());

            /** @var IncomingMailAttachment $attachment */
            foreach ($emailDTO->getAttachments() as $attachment) {
                try {
                    $stream = fopen($attachment->filePath, 'r+');
                    $this->filesystem->writeStream($year.'/'.$month.'/'.$attachment->name, $stream);
                    fclose($stream);
                } catch (\Exception $e) {
                    return;
                }

                $info = new SplFileInfo($attachment->filePath);

                $fileEntity = (new File())
                    ->setTitle($attachment->name)
                    ->setFilename($attachment->name)
                    ->setPath($year.'/'.$month.'/')
                    ->setMimetype(mime_content_type($attachment->filePath))
                    ->setSize($info->getSize());

                $file = $this->fileService->save($fileEntity);

                /** @var FileAssociationNegotiationMessage $fileAssociation */
                $fileAssociation = (new FileAssociationNegotiationMessage())
                    ->setNegotiationMessage($negotiationMessage)
                    ->setFile($file);
                $negotiationMessage->addAttachment($fileAssociation);
            }
        }

        if ($user = $negotiation->getUser()) {
            $negotiationMessage->setUser($user);
        }

        $this->negotiationMessageService->save($negotiationMessage);
    }
}
