<?php

namespace App\Tests\Patient;

use App\Doctor\Entity\Doctor;
use App\Patient\Entity\PatientRecord;
use App\Tests\ApiTestCase;

/**
 * Patient notes: create, list (pinned-first order), edit, pin toggle, delete,
 * validation and tenant ownership scoping.
 */
class PatientNoteTest extends ApiTestCase
{
    /** @return array{0: \App\Auth\Entity\User, 1: PatientRecord} */
    private function recordFor(): array
    {
        $owner  = $this->createUser(['ROLE_DOCTOR']);
        $owner->setRealName('دکتر احمدی');
        $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, $record];
    }

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

        $created = $this->authJson('POST', '/api/v1/patient/' . $record->getUuid() . '/note', $owner, [
            'body' => 'بیمار به دارو حساسیت دارد',
        ]);

        self::assertSame(201, $this->responseCode());
        self::assertSame('بیمار به دارو حساسیت دارد', $created['data']['body']);
        self::assertFalse($created['data']['pinned']);
        self::assertSame('دکتر احمدی', $created['data']['author']);
        self::assertNull($created['data']['updated_at']);
    }

    public function testListReturnsPinnedFirst(): void
    {
        [$owner, $record] = $this->recordFor();
        $base = '/api/v1/patient/' . $record->getUuid();

        // Three notes; the oldest is pinned so it must float above the two newer ones.
        $pinned = $this->authJson('POST', $base . '/note', $owner, ['body' => 'قدیمی پین‌شده', 'pinned' => true]);
        $this->authJson('POST', $base . '/note', $owner, ['body' => 'دوم']);
        $this->authJson('POST', $base . '/note', $owner, ['body' => 'سوم (جدیدترین)']);

        $list = $this->authJson('GET', $base . '/notes', $owner);
        self::assertCount(3, $list['data']);
        self::assertSame($pinned['data']['uuid'], $list['data'][0]['uuid']);
        self::assertTrue($list['data'][0]['pinned']);
        // remaining two are newest-first among the unpinned
        self::assertSame('سوم (جدیدترین)', $list['data'][1]['body']);
        self::assertSame('دوم', $list['data'][2]['body']);
    }

    public function testEditBodyAndTogglePin(): void
    {
        [$owner, $record] = $this->recordFor();
        $created = $this->authJson('POST', '/api/v1/patient/' . $record->getUuid() . '/note', $owner, ['body' => 'اولیه']);
        $uuid    = $created['data']['uuid'];

        $edited = $this->authJson('PATCH', '/api/v1/patient/note/' . $uuid, $owner, [
            'body' => 'ویرایش شد', 'pinned' => true,
        ]);
        self::assertSame(200, $this->responseCode());
        self::assertSame('ویرایش شد', $edited['data']['body']);
        self::assertTrue($edited['data']['pinned']);
        self::assertNotNull($edited['data']['updated_at']);

        // pin-only toggle keeps body intact
        $unpinned = $this->authJson('PATCH', '/api/v1/patient/note/' . $uuid, $owner, ['pinned' => false]);
        self::assertFalse($unpinned['data']['pinned']);
        self::assertSame('ویرایش شد', $unpinned['data']['body']);
    }

    public function testDelete(): void
    {
        [$owner, $record] = $this->recordFor();
        $created = $this->authJson('POST', '/api/v1/patient/' . $record->getUuid() . '/note', $owner, ['body' => 'برای حذف']);
        $uuid    = $created['data']['uuid'];

        $this->authJson('DELETE', '/api/v1/patient/note/' . $uuid, $owner);
        self::assertSame(200, $this->responseCode());

        $after = $this->authJson('GET', '/api/v1/patient/' . $record->getUuid() . '/notes', $owner);
        self::assertCount(0, $after['data']);
    }

    public function testRequiresBodyOnCreate(): void
    {
        [$owner, $record] = $this->recordFor();
        $this->authJson('POST', '/api/v1/patient/' . $record->getUuid() . '/note', $owner, ['body' => '   ']);
        self::assertSame(422, $this->responseCode());
    }

    public function testRejectsEmptyBodyOnEdit(): void
    {
        [$owner, $record] = $this->recordFor();
        $created = $this->authJson('POST', '/api/v1/patient/' . $record->getUuid() . '/note', $owner, ['body' => 'اولیه']);
        $this->authJson('PATCH', '/api/v1/patient/note/' . $created['data']['uuid'], $owner, ['body' => '']);
        self::assertSame(422, $this->responseCode());
    }

    public function testOwnershipScoped(): void
    {
        [$owner, $record] = $this->recordFor();
        $created = $this->authJson('POST', '/api/v1/patient/' . $record->getUuid() . '/note', $owner, ['body' => 'x']);
        $uuid    = $created['data']['uuid'];

        [$other] = $this->recordFor();
        $this->authJson('PATCH', '/api/v1/patient/note/' . $uuid, $other, ['pinned' => true]);
        self::assertSame(404, $this->responseCode());
        $this->authJson('DELETE', '/api/v1/patient/note/' . $uuid, $other);
        self::assertSame(404, $this->responseCode());
    }
}
