<?php

namespace Debugger;

use Exception;
use PHPUnit\Framework\TestCase;
use Velis\Db\Db;
use Velis\Db\Exception as DbException;
use Velis\Debugger\ErrorMailFactory;
use Velis\Debugger\ErrorReporter;
use Velis\Log\LoggerInterface;
use Velis\Mail\Mail;
use Velis\Model\DataObject\NoColumnsException;

class ErrorReporterTest extends TestCase
{
    /**
     * @throws NoColumnsException
     */
    public function testReport(): void
    {
        $mail = $this->createMock(Mail::class);
        $mail->expects($this->once())
            ->method('send');

        $mailFactory = $this->createMock(ErrorMailFactory::class);
        $mailFactory->expects($this->once())
            ->method('createMail')
            ->willReturn($mail);

        $db = $this->createMock(Db::class);
        $dbExceptionLogger = $this->createMock(LoggerInterface::class);
        $logger = $this->createMock(LoggerInterface::class);

        $reporter = new ErrorReporter(
            $mailFactory,
            $db,
            $dbExceptionLogger,
            $logger,
        );

        $reporter->report(new Exception());
    }

    public function testLogWithDbException(): void
    {
        $mailFactory = $this->createMock(ErrorMailFactory::class);
        $db = $this->createMock(Db::class);

        $dbExceptionLogger = $this->createMock(LoggerInterface::class);
        $dbExceptionLogger->expects($this->once())
            ->method('error');

        $logger = $this->createMock(LoggerInterface::class);
        $logger->expects($this->never())
            ->method('error');

        $reporter = new ErrorReporter(
            $mailFactory,
            $db,
            $dbExceptionLogger,
            $logger,
        );

        $reporter->log(new DbException());
    }

    public function testLogWithOtherException(): void
    {
        $mailFactory = $this->createMock(ErrorMailFactory::class);
        $db = $this->createMock(Db::class);

        $dbExceptionLogger = $this->createMock(LoggerInterface::class);
        $dbExceptionLogger->expects($this->never())
            ->method('error');

        $logger = $this->createMock(LoggerInterface::class);
        $logger->expects($this->once())
            ->method('error');

        $reporter = new ErrorReporter(
            $mailFactory,
            $db,
            $dbExceptionLogger,
            $logger,
        );

        $reporter->log(new Exception());
    }

    public function testLogWhenDbIsNotInitialized(): void
    {
        $mailFactory = $this->createMock(ErrorMailFactory::class);
        $db = null;

        $dbExceptionLogger = $this->createMock(LoggerInterface::class);
        $dbExceptionLogger->expects($this->never())
            ->method('error');

        $logger = $this->createMock(LoggerInterface::class);
        $logger->expects($this->once())
            ->method('error');

        $reporter = new ErrorReporter(
            $mailFactory,
            $db,
            $dbExceptionLogger,
            $logger,
        );

        $reporter->log(new Exception());
    }
}
