<?php

namespace Mailbox\Application;

use Mailbox\Domain\Attachment\Attachment;
use Mailbox\Domain\Attachment\AttachmentCollection;
use Mailbox\Domain\MailBox\MailBox;
use Mailbox\Domain\Message\Message;
use Mailbox\Domain\Message\VolueObject\From;
use Mailbox\Infrastructure\Repositories\ImapMessageRepository;
use PHPUnit\Framework\TestCase;

class MailBoxServiceTest extends TestCase
{

    /**
     * @var Exporter
     */
    protected $object;


    /**
     * @param string $path
     * @return MailBoxService
     */
    private static function createService(string $path, string $hash): MailBoxService
    {
        $protocol = new \Mailbox\Infrastructure\ProtocolAdapter\TestProtocol(
            $path
        );
        $config = (new \Mailbox\Application\Config())
            ->setCacheDir(__DIR__ . '/../../../sandbox/cache/tests')
            ->setLogin($hash . '@mail.ru')
            ->setPassword($hash)
            ->setAttachmentsDir(__DIR__ . '/../../../sandbox/attachments/tests');

        return new MailBoxService(
            new ImapMessageRepository($protocol, $config)
        );
    }


    /**
     * Исправлена
     * @covers \Mailbox\Application\MailBoxService::getMessageById
     * @throws \Repo\Concrete\Exceptions\Collection
     */
    public function testGetMessageByIdIncorrectMailFrom()
    {
        $path = __DIR__ . '/../../mails/YandexInvalidArgument.eml';
        $hash = md5($path);
        $this->object = self::createService($path, $hash);

        $validMessage = (new Message())
            ->setUid(1)
            ->setId(1)
            ->setDateTime(new \DateTime('2020-06-29 06:23:18', new \DateTimeZone('GMT')))
            ->setFromEmail(new From('partssales1@autopole.ru', 'Роман И. Шефер'))
            ->setSubject('Прайс остатки')
            ->setMessageId('<e09bb4bdbba24fe483dbb4d9020a2bdf@SKSR-MAIL.auto.local>')
            ->setMailBox((new MailBox('INBOX'))->setId('INBOX'))
            ->setFlagSeen(false)
            ->setAttachmentCollection(
                (new AttachmentCollection())
                    ->push(
                        (new Attachment('image001.jpg'))
                            ->setMessageKey(1)
                            ->setId(2)
                            ->setMessageId(1)
                            ->setFilePath(
                                __DIR__ . '/../../../sandbox/attachments/tests/' . $hash . '@mail.ru/1/2/image001.jpg'
                            )
                    )
            );

        $testMessage = $this->object->getMessageById(1);


        $validObject = $validMessage->getAttachmentCollection()->current();
        $testObject = $testMessage->getAttachmentCollection()->current();

        $validMessage->getAttachmentCollection()->offsetUnset($validObject);
        $testMessage->getAttachmentCollection()->offsetUnset($testObject);

        //всем указываем один хеш объекта иначе никогда не получится сравнить
        $validMessage->getAttachmentCollection()->offsetSet($validObject, $hash);
        $testMessage->getAttachmentCollection()->offsetSet($testObject, $hash);

        $this->assertEquals($validMessage, $testMessage);
    }

    /**
     * Исправлена
     * @covers \Mailbox\Application\MailBoxService::getMessageById
     * @throws \Repo\Concrete\Exceptions\Collection
     */
    public function testGetMessageByIdIncorrectMailFrom2()
    {
        $path = __DIR__ . '/../../mails/IsNotValidEmailAddress.eml';
        $hash = md5($path);
        $this->object = self::createService($path, $hash);

        $validMessage = (new Message())
            ->setUid(1)
            ->setId(1)
            ->setDateTime(new \DateTime('2020-06-30 03:30:21', new \DateTimeZone('GMT+03')))
            ->setFromEmail(new From('robot.msk@autozap.ru', 'Academy_Plus'))
            ->setSubject('PriceUSA')
            ->setMessageId('<1458304217.20200630033021@Don\'t reply for this mail>')
            ->setMailBox((new MailBox('INBOX'))->setId('INBOX'))
            ->setFlagSeen(false)
            ->setAttachmentCollection(
                (new AttachmentCollection())
                    ->push(
                        (new Attachment('PriceUSA.rar'))
                            ->setMessageKey(1)
                            ->setId(2)
                            ->setMessageId(1)
                            ->setFilePath(
                                __DIR__ . '/../../../sandbox/attachments/tests/' . $hash . '@mail.ru/1/2/priceusa.rar'
                            )
                    )
            );

        $testMessage = $this->object->getMessageById(1);


        $validObject = $validMessage->getAttachmentCollection()->current();
        $testObject = $testMessage->getAttachmentCollection()->current();

        $validMessage->getAttachmentCollection()->offsetUnset($validObject);
        $testMessage->getAttachmentCollection()->offsetUnset($testObject);

        //всем указываем один хеш объекта иначе никогда не получится сравнить
        $validMessage->getAttachmentCollection()->offsetSet($validObject, $hash);
        $testMessage->getAttachmentCollection()->offsetSet($testObject, $hash);

        $this->assertEquals($validMessage, $testMessage);
    }

    /**
     * Исправлена
     * @covers \Mailbox\Application\MailBoxService::getMessageById
     * @throws \Repo\Concrete\Exceptions\Collection
     */
    public function testGetMessageByIdIncorrectSubject()
    {
        $path = __DIR__ . '/../../mails/ErrorSubject2.eml';
        $hash = md5($path);
        $this->object = self::createService($path, $hash);

        $validMessage = (new Message())
            ->setUid(1)
            ->setId(1)
            ->setDateTime(new \DateTime('2020-07-07 12:00:04', new \DateTimeZone('GMT+03')))
            ->setFromEmail(new From('info@euroautocenter.ru', 'ЕвроАвтоЦентр'))
            ->setSubject('Прайс наличия STARKE Automotive')
            ->setMessageId('<542ffdc8-204e-4174-9f0e-5424de9f93de@euroautocenter.ru>')
            ->setMailBox((new MailBox('INBOX'))->setId('INBOX'))
            ->setFlagSeen(false)
            ->setAttachmentCollection(
                (new AttachmentCollection())
                    ->push(
                        (new Attachment('price-eac.zip'))
                            ->setMessageKey(1)
                            ->setId(2)
                            ->setMessageId(1)
                            ->setFilePath(
                                __DIR__ . '/../../../sandbox/attachments/tests/' . $hash . '@mail.ru/1/2/priceeac.zip'
                            )
                    )
            );

        $testMessage = $this->object->getMessageById(1);


        $validObject = $validMessage->getAttachmentCollection()->current();
        $testObject = $testMessage->getAttachmentCollection()->current();

        $validMessage->getAttachmentCollection()->offsetUnset($validObject);
        $testMessage->getAttachmentCollection()->offsetUnset($testObject);

        //всем указываем один хеш объекта иначе никогда не получится сравнить
        $validMessage->getAttachmentCollection()->offsetSet($validObject, $hash);
        $testMessage->getAttachmentCollection()->offsetSet($testObject, $hash);

        $this->assertEquals($validMessage, $testMessage);
    }

    /**
     * Исправлена
     * @covers \Mailbox\Application\MailBoxService::getMessageById
     * @throws \Repo\Concrete\Exceptions\Collection
     */
    public function testGetMessageByIdIncorrectDoubleSubject()
    {
        $path = __DIR__ . '/../../mails/DoubleSubjectDecode.eml';
        $hash = md5($path);
        $this->object = self::createService($path, $hash);

        $validMessage = (new Message())
            ->setUid(1)
            ->setId(1)
            ->setDateTime(new \DateTime('2020-07-08 12:06:51', new \DateTimeZone('GMT+07')))
            ->setFromEmail(new From('no-reply@autotrade.su', null))
            ->setSubject('Прайс общий Москва Апаринки')
            ->setMessageId('<E1jt2IW-0004Aw-DC.no-reply-autotrade-su@mx198.i.mail.ru>')
            ->setMailBox((new MailBox('INBOX'))->setId('INBOX'))
            ->setFlagSeen(false)
            ->setAttachmentCollection(
                (new AttachmentCollection())
                    ->push(
                        (new Attachment('Прайс лист для клиентов.xlsx'))
                            ->setMessageKey(1)
                            ->setId(1)
                            ->setMessageId(1)
                            ->setFilePath(
                                __DIR__ . '/../../../sandbox/attachments/tests/' .
                                $hash . '@mail.ru/1/1/praislistdlyaclientov.xlsx'
                            )
                    )
            );

        $testMessage = $this->object->getMessageById(1);


        $validObject = $validMessage->getAttachmentCollection()->current();
        $testObject = $testMessage->getAttachmentCollection()->current();

        $validMessage->getAttachmentCollection()->offsetUnset($validObject);
        $testMessage->getAttachmentCollection()->offsetUnset($testObject);

        //всем указываем один хеш объекта иначе никогда не получится сравнить
        $validMessage->getAttachmentCollection()->offsetSet($validObject, $hash);
        $testMessage->getAttachmentCollection()->offsetSet($testObject, $hash);

        $this->assertEquals($validMessage, $testMessage);
    }

    /**
     * Исправлена
     * @covers \Mailbox\Application\MailBoxService::getMessageById
     * @throws \Repo\Concrete\Exceptions\Collection
     */
    public function testGetMessageByIdIncorrectAttachment()
    {
        $path = __DIR__ . '/../../mails/ErrorAtachment3.eml';
        $hash = md5($path);
        $this->object = self::createService($path, $hash);

        $validMessage = (new Message())
            ->setUid(1)
            ->setId(1)
            ->setDateTime(new \DateTime('2020-07-07 17:10:31', new \DateTimeZone('GMT+03')))
            ->setFromEmail(new From('ae@autoeuro.ru', 'www.autoeuro.ru'))
            ->setSubject('Индивидуальный прайс от www.autoeuro.ru')
            ->setMessageId('<E1jsoIp-0006Dx-IA@ads640.hs.shared.masterhost.ru>')
            ->setMailBox((new MailBox('INBOX'))->setId('INBOX'))
            ->setFlagSeen(false)
            ->setAttachmentCollection(
                (new AttachmentCollection())
                    ->push(
                        (new Attachment('PriceAE_(769624293).zip'))
                            ->setMessageKey(1)
                            ->setId(2)
                            ->setMessageId(1)
                            ->setFilePath(
                                __DIR__ . '/../../../sandbox/attachments/tests/' .
                                $hash . '@mail.ru/1/2/priceae769624293.zip'
                            )
                    )
            );

        $testMessage = $this->object->getMessageById(1);


        $validObject = $validMessage->getAttachmentCollection()->current();
        $testObject = $testMessage->getAttachmentCollection()->current();

        $validMessage->getAttachmentCollection()->offsetUnset($validObject);
        $testMessage->getAttachmentCollection()->offsetUnset($testObject);

        //всем указываем один хеш объекта иначе никогда не получится сравнить
        $validMessage->getAttachmentCollection()->offsetSet($validObject, $hash);
        $testMessage->getAttachmentCollection()->offsetSet($testObject, $hash);

        $this->assertEquals($validMessage, $testMessage);
    }

    /**
     * Исправлена
     * @covers \Mailbox\Application\MailBoxService::getMessageById
     * @throws \Repo\Concrete\Exceptions\Collection
     */
    public function testGetMessageByIdIncorrectAttachment2()
    {
        $path = __DIR__ . '/../../mails/ErrorEndLine.eml';
        $hash = md5($path);
        $this->object = self::createService($path, $hash);

        $validMessage = (new Message())
            ->setUid(1)
            ->setId(1)
            ->setDateTime(new \DateTime('2020-07-09 08:04:15', new \DateTimeZone('GMT+03')))
            ->setFromEmail(new From('sales@auto-tech.ru', 'Интернет-магазин auto-tech.ru'))
            ->setSubject('Прайслист общий')
            ->setMessageId('<AM0PR05MB528227E8E2CE6A101B64543683640@AM0PR05MB5282.eurprd05.prod.outlook.com>')
            ->setMailBox((new MailBox('INBOX'))->setId('INBOX'))
            ->setFlagSeen(false)
            ->setAttachmentCollection(
                (new AttachmentCollection())
                    ->push(
                        (new Attachment('Прайслист.xls'))
                            ->setMessageKey(1)
                            ->setId(2)
                            ->setMessageId(1)
                            ->setFilePath(
                                __DIR__ . '/../../../sandbox/attachments/tests/' .
                                $hash . '@mail.ru/1/2/praislist.xls'
                            )
                    )
            );

        $testMessage = $this->object->getMessageById(1);


        $validObject = $validMessage->getAttachmentCollection()->current();
        $testObject = $testMessage->getAttachmentCollection()->current();

        $validMessage->getAttachmentCollection()->offsetUnset($validObject);
        $testMessage->getAttachmentCollection()->offsetUnset($testObject);

        //всем указываем один хеш объекта иначе никогда не получится сравнить
        $validMessage->getAttachmentCollection()->offsetSet($validObject, $hash);
        $testMessage->getAttachmentCollection()->offsetSet($testObject, $hash);

        $this->assertEquals($validMessage, $testMessage);
    }

    /**
     * Пи сьмо с кривым from
     * @throws \Exception
     */
    public function testGetMessageByIdIncorrectFrom()
    {
        $path = __DIR__ . '/../../mails/ErrrorFrom.eml';
        $hash = md5($path);
        $this->object = self::createService($path, $hash);

        $validMessage = (new Message())
            ->setUid(1)
            ->setId(1)
            ->setDateTime(new \DateTime('2020-07-09 11:18:10', new \DateTimeZone('GMT+03')))
            ->setFromEmail(new From('sale@avtomedon-m.ru', 'AMD'))
            ->setSubject('Новинки "За месяц"')
            ->setMessageId('<43c2bde54e02775eaba16e919f3cae03@mlsend.com>')
            ->setMailBox((new MailBox('INBOX'))->setId('INBOX'))
            ->setFlagSeen(false)
            ->setAttachmentCollection(new AttachmentCollection())
            ;

        $testMessage = $this->object->getMessageById(1);


        $this->assertEquals($validMessage, $testMessage);
    }
}
