<?php

namespace App\Tests\Patient;

use App\Doctor\Entity\Doctor;
use App\Inventory\Entity\InventoryItem;
use App\Inventory\Entity\InventoryPackage;
use App\Patient\Entity\PatientRecord;
use App\Tests\ApiTestCase;

/**
 * ثبت مراجعه با کالای مصرفی/پکیج/زمان پذیرش (ویزارد ثبت مراجعه):
 * POST /patient/{uuid}/session با consumables (سهم بیمار کامل، بدون بیمه)،
 * inventory_package_uuid (مرجع) و session_at. آیتم‌های tenant دیگر بی‌صدا رد می‌شوند.
 */
class SessionConsumableTest extends ApiTestCase
{
    /** @return array{0: \App\Auth\Entity\User, 1: Doctor, 2: PatientRecord} */
    private function recordFor(): array
    {
        $owner  = $this->createUser(['ROLE_DOCTOR']);
        $doctor = new Doctor($owner, 'دکتر');
        $this->em->persist($doctor);
        $this->em->flush();

        $patient = $this->createUser(['ROLE_USER']);
        $record  = new PatientRecord('doctor', $doctor->getId(), $patient, 'doctor', $doctor->getId());
        $this->em->persist($record);
        $this->em->flush();

        return [$owner, $doctor, $record];
    }

    private function itemFor(Doctor $doctor, string $name, int $price): InventoryItem
    {
        $item = new InventoryItem('doctor', $doctor->getId(), $name);
        $item->setPrice($price)->setStock(100);
        $this->em->persist($item);
        $this->em->flush();

        return $item;
    }

    // ── موفق ────────────────────────────────────────────────────────────────

    public function testCreateSessionWithConsumablesPackageAndSessionAt(): void
    {
        [$owner, $doctor, $record] = $this->recordFor();
        $glasses = $this->itemFor($doctor, 'عینک', 1_200_000);
        $pencil  = $this->itemFor($doctor, 'مداد سفید', 300_000);

        $package = new InventoryPackage('doctor', $doctor->getId(), 'پکیج زیبایی');
        $this->em->persist($package);
        $this->em->flush();

        $res = $this->authJson('POST', '/api/v1/patient/' . $record->getUuid() . '/session', $owner, [
            'visit_price_rials'      => 500_000,
            'session_at'             => 1_760_000_000,
            'inventory_package_uuid' => $package->getUuid(),
            'consumables'            => [
                ['inventory_item_uuid' => $glasses->getUuid(), 'quantity' => 2],
                ['inventory_item_uuid' => $pencil->getUuid()],
            ],
        ]);

        self::assertSame(201, $this->responseCode());
        self::assertSame(1_760_000_000, $res['data']['session_at']);
        self::assertSame($package->getUuid(), $res['data']['inventory_package_uuid']);
        self::assertSame('پکیج زیبایی', $res['data']['inventory_package_title']);

        self::assertCount(2, $res['data']['consumables']);
        self::assertSame(2_700_000, $res['data']['consumables_total_rials']); // 2×1٬200٬000 + 300٬000

        $byName = array_column($res['data']['consumables'], null, 'item_name');
        self::assertSame(2, $byName['عینک']['quantity']);
        self::assertSame(2_400_000, $byName['عینک']['line_total_rials']);
        self::assertSame(1, $byName['مداد سفید']['quantity']);

        // کالاها بدون پوشش بیمه → کامل روی سهم بیمار
        self::assertSame(3_200_000, $res['data']['final_price_rials']); // ویزیت 500٬000 + کالاها 2٬700٬000
    }

    public function testConsumablesAppearInSessionsList(): void
    {
        [$owner, $doctor, $record] = $this->recordFor();
        $item = $this->itemFor($doctor, 'سرنگ', 50_000);

        $this->authJson('POST', '/api/v1/patient/' . $record->getUuid() . '/session', $owner, [
            'visit_price_rials' => 0,
            'consumables'       => [['inventory_item_uuid' => $item->getUuid(), 'quantity' => 3]],
        ]);
        self::assertSame(201, $this->responseCode());

        $sessions = $this->authJson('GET', '/api/v1/patient/' . $record->getUuid() . '/sessions', $owner);
        self::assertCount(1, $sessions['data'][0]['consumables']);
        self::assertSame(150_000, $sessions['data'][0]['consumables_total_rials']);
        self::assertSame(150_000, $sessions['data'][0]['patient_debt_rials']);
    }

    // ── خطا ─────────────────────────────────────────────────────────────────

    public function testForeignTenantConsumableAndPackageSilentlySkipped(): void
    {
        [$owner, , $record] = $this->recordFor();

        // tenant دیگر
        $otherOwner  = $this->createUser(['ROLE_DOCTOR']);
        $otherDoctor = new Doctor($otherOwner, 'دکتر دیگر');
        $this->em->persist($otherDoctor);
        $this->em->flush();
        $foreignItem    = $this->itemFor($otherDoctor, 'آمپول', 900_000);
        $foreignPackage = new InventoryPackage('doctor', $otherDoctor->getId(), 'پکیج دیگری');
        $this->em->persist($foreignPackage);
        $this->em->flush();

        $res = $this->authJson('POST', '/api/v1/patient/' . $record->getUuid() . '/session', $owner, [
            'visit_price_rials'      => 400_000,
            'inventory_package_uuid' => $foreignPackage->getUuid(),
            'consumables'            => [['inventory_item_uuid' => $foreignItem->getUuid(), 'quantity' => 5]],
        ]);

        self::assertSame(201, $this->responseCode());
        self::assertCount(0, $res['data']['consumables']);
        self::assertSame(0, $res['data']['consumables_total_rials']);
        self::assertNull($res['data']['inventory_package_uuid']);
        self::assertSame(400_000, $res['data']['final_price_rials']);
    }

    public function testUnknownConsumableUuidSkipped(): void
    {
        [$owner, , $record] = $this->recordFor();

        $res = $this->authJson('POST', '/api/v1/patient/' . $record->getUuid() . '/session', $owner, [
            'visit_price_rials' => 200_000,
            'consumables'       => [['inventory_item_uuid' => '00000000-0000-0000-0000-000000000000']],
        ]);

        self::assertSame(201, $this->responseCode());
        self::assertCount(0, $res['data']['consumables']);
        self::assertSame(200_000, $res['data']['final_price_rials']);
    }

    // ── مرزی ────────────────────────────────────────────────────────────────

    public function testEmptyConsumablesAndNoSessionAtDefaults(): void
    {
        [$owner, , $record] = $this->recordFor();

        $res = $this->authJson('POST', '/api/v1/patient/' . $record->getUuid() . '/session', $owner, [
            'visit_price_rials' => 100_000,
            'consumables'       => [],
        ]);

        self::assertSame(201, $this->responseCode());
        self::assertSame([], $res['data']['consumables']);
        self::assertSame(0, $res['data']['consumables_total_rials']);
        self::assertNull($res['data']['session_at']);
        self::assertNull($res['data']['inventory_package_uuid']);
    }

    public function testZeroQuantityCoercedToOne(): void
    {
        [$owner, $doctor, $record] = $this->recordFor();
        $item = $this->itemFor($doctor, 'گاز استریل', 80_000);

        $res = $this->authJson('POST', '/api/v1/patient/' . $record->getUuid() . '/session', $owner, [
            'visit_price_rials' => 0,
            'consumables'       => [['inventory_item_uuid' => $item->getUuid(), 'quantity' => 0]],
        ]);

        self::assertSame(201, $this->responseCode());
        self::assertSame(1, $res['data']['consumables'][0]['quantity']);
        self::assertSame(80_000, $res['data']['consumables_total_rials']);
    }
}
