<?php

namespace App\Tests\Appointment;

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

/**
 * تاریخ خاص و تعطیلات باید دقیقاً همان روزِ ارسالی را نگه دارند: timestamp روی
 * نیمه‌شبِ محلی و یک رشتهٔ `Y-m-d` کانونی در پاسخ، تا کلاینت مجبور به تبدیل
 * timestamp (و جابه‌جایی یک‌روزه به‌خاطر UTC) نباشد.
 */
class SpecialDateBoundaryTest extends ApiTestCase
{
    private function makeDoctor(): Doctor
    {
        $owner  = $this->createUser(['ROLE_DOCTOR']);
        $doctor = new Doctor($owner, 'دکتر تاریخ');
        $this->em->persist($doctor);
        $this->em->flush();

        return $doctor;
    }

    public function testOverrideKeepsExactDayAndReturnsDateString(): void
    {
        $doctor = $this->makeDoctor();
        $date   = date('Y-m-d', strtotime('+9 days'));

        $body = $this->authJson('POST', '/api/v1/appointment-settings/date-override', $doctor->getUser(), [
            'doctor_uuid' => $doctor->getUuid(),
            'date'        => $date,
            'active'      => false,
        ]);

        self::assertSame(201, $this->responseCode());
        self::assertSame($date, $body['data']['data']['date_string']);
        self::assertSame((int) strtotime($date . ' 00:00:00'), $body['data']['data']['date']);
        self::assertSame($date, date('Y-m-d', $body['data']['data']['date']));
    }

    public function testOverrideNormalizesTimestampWithTimeToLocalMidnight(): void
    {
        $doctor = $this->makeDoctor();
        $date   = date('Y-m-d', strtotime('+10 days'));

        // ورودی ISO با ساعت (مثل چیزی که toISOString مرورگر می‌سازد) نباید روز را جابه‌جا کند.
        $body = $this->authJson('POST', '/api/v1/appointment-settings/date-override', $doctor->getUser(), [
            'doctor_uuid' => $doctor->getUuid(),
            'date'        => $date . ' 23:45:00',
            'active'      => false,
        ]);

        self::assertSame(201, $this->responseCode());
        self::assertSame($date, $body['data']['data']['date_string']);
        self::assertSame((int) strtotime($date . ' 00:00:00'), $body['data']['data']['date']);
    }

    public function testOverridePatchKeepsExactDay(): void
    {
        $doctor = $this->makeDoctor();
        $first  = date('Y-m-d', strtotime('+11 days'));
        $second = date('Y-m-d', strtotime('+12 days'));

        $created = $this->authJson('POST', '/api/v1/appointment-settings/date-override', $doctor->getUser(), [
            'doctor_uuid' => $doctor->getUuid(),
            'date'        => $first,
            'active'      => false,
        ]);
        $uuid = $created['data']['data']['uuid'];

        $patched = $this->authJson('PATCH', "/api/v1/appointment-settings/date-override/{$uuid}", $doctor->getUser(), [
            'date' => $second,
        ]);

        self::assertSame(200, $this->responseCode());
        self::assertSame($second, $patched['data']['data']['date_string']);
    }

    public function testHolidayKeepsExactDaysAndReturnsDateStrings(): void
    {
        $doctor = $this->makeDoctor();
        $start  = date('Y-m-d', strtotime('+13 days'));
        $end    = date('Y-m-d', strtotime('+15 days'));

        $body = $this->authJson('POST', '/api/v1/appointment-settings/holidays', $doctor->getUser(), [
            'doctor_uuid' => $doctor->getUuid(),
            'start_date'  => $start,
            'end_date'    => $end,
            'reason'      => 'سفر',
        ]);

        self::assertSame(201, $this->responseCode());
        self::assertSame($start, $body['data']['data']['start_date_string']);
        self::assertSame($end,   $body['data']['data']['end_date_string']);
        self::assertSame((int) strtotime($start . ' 00:00:00'), $body['data']['data']['start_date']);
        self::assertSame((int) strtotime($end . ' 00:00:00'),   $body['data']['data']['end_date']);
    }

    public function testInvalidDateIsRejected(): void
    {
        $doctor = $this->makeDoctor();

        $this->authJson('POST', '/api/v1/appointment-settings/date-override', $doctor->getUser(), [
            'doctor_uuid' => $doctor->getUuid(),
            'date'        => 'not-a-date',
            'active'      => false,
        ]);

        self::assertSame(422, $this->responseCode());
    }
}
