<?php

declare(strict_types=1);

namespace OCA\Mitgliederverwaltung\Tests\Service;

use OCA\Mitgliederverwaltung\Db\SaleRecord;
use OCA\Mitgliederverwaltung\Db\SaleRecordMapper;
use OCA\Mitgliederverwaltung\Service\AuditService;
use OCA\Mitgliederverwaltung\Service\SaleService;
use PHPUnit\Framework\MockObject\MockObject;
use PHPUnit\Framework\TestCase;
use Psr\Log\LoggerInterface;

class SaleServiceTest extends TestCase {

    private SaleService $service;
    private SaleRecordMapper&MockObject $saleRecordMapper;
    private AuditService&MockObject $auditService;
    private LoggerInterface&MockObject $logger;

    protected function setUp(): void {
        parent::setUp();

        $this->saleRecordMapper = $this->createMock(SaleRecordMapper::class);
        $this->auditService = $this->createMock(AuditService::class);
        $this->logger = $this->createMock(LoggerInterface::class);

        $this->service = new SaleService(
            $this->saleRecordMapper,
            $this->auditService,
            $this->logger
        );
    }

    private function saleEntity(int $id = 1, int $stockItemId = 1, int $variantId = 1, int $quantity = 2, string $unitPrice = '25.00'): SaleRecord {
        $entity = new SaleRecord();
        $entity->setId($id);
        $entity->setStockItemId($stockItemId);
        $entity->setVariantId($variantId);
        $entity->setDate('2026-04-21');
        $entity->setQuantity($quantity);
        $entity->setUnitPrice($unitPrice);
        $entity->setTotalPrice((string)((float)$unitPrice * $quantity));
        $entity->setNotes(null);
        $entity->setCreatedAt('2026-04-21 00:00:00');
        return $entity;
    }

    public function testCreateSale_auditLogged(): void {
        $this->saleRecordMapper->method('insert')->willReturnCallback(function ($entity) use ($stockItemId = 1) {
            $entity->setId(1);
        });

        $this->auditService->method('logCreate')->willReturnCallback(function(array $data, string $type, int $id) {
            $this->assertSame(1, $data['stock_item_id']);
            $this->assertSame('inventory_sale', $type);
            $this->assertSame(1, $id);
        });

        $result = $this->service->createSale([
            'stock_item_id' => 1,
            'variant_id' => 1,
            'date' => '2026-04-21',
            'quantity' => 2,
            'unit_price' => '25.00',
            'notes' => null,
        ]);

        $this->assertSame('50.00', $result->getTotalPrice());
    }

    public function testSaleRecord_totalCalculation(): void {
        $sale = $this->saleEntity(1, 1, 1, 3, '15.00');
        $expectedTotal = (float)$sale->getQuantity() * (float)$sale->getUnitPrice();
        $actualTotal = (float)$sale->getTotalPrice();
        $this->assertEqualsWithDelta($expectedTotal, $actualTotal, 0.01);
    }

    public function testSaleRecord_totalCalculationZero(): void {
        $sale = $this->saleEntity(1, 1, 1, 0, '0.00');
        $expectedTotal = 0.0;
        $actualTotal = (float)$sale->getTotalPrice();
        $this->assertEqualsWithDelta($expectedTotal, $actualTotal, 0.01);
    }
}
