<?php

namespace App\Tests\Secretary;

use App\Auth\Entity\User;
use App\Doctor\Entity\Doctor;
use App\Secretary\Entity\DoctorSecretary;
use App\Tests\ApiTestCase;

/**
 * اندپوینت‌های مدیریت سهم منشی (ادمین) و گزارش/شبا (پنل منشی).
 */
class SecretaryShareApiTest extends ApiTestCase
{
    /** @return array{0: DoctorSecretary, 1: User} */
    private function makeRelation(): array
    {
        $doctorUser = $this->createUser(['ROLE_USER', 'ROLE_DOCTOR']);
        $doctor     = new Doctor($doctorUser, 'دکتر تست API سهم');
        $this->em->persist($doctor);

        $secretaryUser = $this->createUser(['ROLE_USER', 'ROLE_SECRETARY']);
        $relation      = new DoctorSecretary($doctor, $secretaryUser);
        $this->em->persist($relation);
        $this->em->flush();

        return [$relation, $secretaryUser];
    }

    // ── ادمین ────────────────────────────────────────────────────────────────

    public function testAdminSeesTheRelationDetailWithEarnings(): void
    {
        [$relation] = $this->makeRelation();
        $admin      = $this->createUser(['ROLE_ADMIN']);

        $body = $this->authJson('GET', '/api/v1/admin/secretary/' . $relation->getUuid(), $admin);

        self::assertSame(200, $this->responseCode());
        $row = $body['data']['data'];
        self::assertFalse($row['online_share_enabled']);
        // JSON عددِ گِرد را بدون ممیز می‌دهد، پس مقایسه‌ی نوع‌آزاد.
        self::assertEquals(0, $row['online_share_percent']);
        self::assertSame(0, $row['earnings']['total_rials']);
    }

    public function testAdminEnablesTheShareWithAPercent(): void
    {
        [$relation] = $this->makeRelation();
        $admin      = $this->createUser(['ROLE_ADMIN']);

        $body = $this->authJson('PUT', '/api/v1/admin/secretary/' . $relation->getUuid() . '/online-share', $admin, [
            'enabled' => true,
            'percent' => 5,
        ]);

        self::assertSame(200, $this->responseCode());
        self::assertTrue($body['data']['data']['online_share_enabled']);
        self::assertEquals(5, $body['data']['data']['online_share_percent']);
    }

    public function testPercentAbove100IsRejected(): void
    {
        [$relation] = $this->makeRelation();
        $admin      = $this->createUser(['ROLE_ADMIN']);

        $this->authJson('PUT', '/api/v1/admin/secretary/' . $relation->getUuid() . '/online-share', $admin, [
            'enabled' => true, 'percent' => 101,
        ]);

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

    public function testEnablingWithoutAPercentIsRejected(): void
    {
        [$relation] = $this->makeRelation();
        $admin      = $this->createUser(['ROLE_ADMIN']);

        $this->authJson('PUT', '/api/v1/admin/secretary/' . $relation->getUuid() . '/online-share', $admin, [
            'enabled' => true, 'percent' => 0,
        ]);

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

    public function testNonAdminIsForbidden(): void
    {
        [$relation, $secretaryUser] = $this->makeRelation();

        $this->authJson('GET', '/api/v1/admin/secretary/' . $relation->getUuid(), $secretaryUser);

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

    public function testUnknownRelationIsNotFound(): void
    {
        $admin = $this->createUser(['ROLE_ADMIN']);

        $this->authJson('GET', '/api/v1/admin/secretary/00000000-0000-4000-8000-000000000000', $admin);

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

    // ── پنل منشی ─────────────────────────────────────────────────────────────

    public function testSummaryReportsDisabledWhenNoRelationHasAShare(): void
    {
        [, $secretaryUser] = $this->makeRelation();

        $body = $this->authJson('GET', '/api/v1/secretary/earnings/summary', $secretaryUser);

        self::assertSame(200, $this->responseCode());
        self::assertFalse($body['data']['data']['enabled']);
        self::assertSame(0, $body['data']['data']['total_rials']);
    }

    public function testSummaryReportsEnabledWithThePercentOnceAdminTurnsItOn(): void
    {
        [$relation, $secretaryUser] = $this->makeRelation();
        $relation->setOnlineShareEnabled(true)->setOnlineSharePercent(7.5);
        $this->em->flush();

        $body = $this->authJson('GET', '/api/v1/secretary/earnings/summary', $secretaryUser);

        self::assertSame(200, $this->responseCode());
        self::assertTrue($body['data']['data']['enabled']);
        self::assertSame(7.5, $body['data']['data']['share_percent']);
    }

    public function testReportIsEmptyButSucceedsWithoutEarnings(): void
    {
        [, $secretaryUser] = $this->makeRelation();

        $body = $this->authJson('GET', '/api/v1/secretary/earnings/report', $secretaryUser);

        self::assertSame(200, $this->responseCode());
        self::assertSame([], $body['data']);
        self::assertSame(0, $body['meta']['totalRecords']);
    }

    public function testSecretaryManagesItsIbans(): void
    {
        [, $secretaryUser] = $this->makeRelation();

        $added = $this->authJson('POST', '/api/v1/secretary/iban', $secretaryUser, [
            'iban' => 'IR' . str_pad((string) random_int(0, 999_999), 24, '0', STR_PAD_LEFT),
            'bank_name' => 'ملی',
        ]);
        self::assertSame(201, $this->responseCode());
        $ibans = $added['data']['data']['bank_account'];
        self::assertCount(1, $ibans);
        // شبای تازه تأییدنشده است؛ تسویه با آن مجاز نیست.
        self::assertFalse($ibans[0]['verified']);

        $removed = $this->authJson('DELETE', '/api/v1/secretary/iban/' . $ibans[0]['id'], $secretaryUser);
        self::assertSame(200, $this->responseCode());
        self::assertSame([], $removed['data']['data']['bank_account']);
    }

    public function testInvalidIbanIsRejected(): void
    {
        [, $secretaryUser] = $this->makeRelation();

        $this->authJson('POST', '/api/v1/secretary/iban', $secretaryUser, ['iban' => '12345']);

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

    public function testThirdIbanIsRejected(): void
    {
        [, $secretaryUser] = $this->makeRelation();
        $iban = fn() => 'IR' . str_pad((string) random_int(0, 999_999_999), 24, '0', STR_PAD_LEFT);

        $this->authJson('POST', '/api/v1/secretary/iban', $secretaryUser, ['iban' => $iban()]);
        $this->authJson('POST', '/api/v1/secretary/iban', $secretaryUser, ['iban' => $iban()]);
        $this->authJson('POST', '/api/v1/secretary/iban', $secretaryUser, ['iban' => $iban()]);

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

    public function testSettlementAcceptsAVerifiedSecretaryIban(): void
    {
        [, $secretaryUser] = $this->makeRelation();

        $added = $this->authJson('POST', '/api/v1/secretary/iban', $secretaryUser, [
            'iban' => 'IR' . str_pad((string) random_int(0, 999_999), 24, '0', STR_PAD_LEFT),
        ]);
        $ibanId = $added['data']['data']['bank_account'][0]['id'];

        // تأیید شبا کارِ ادمین است؛ اینجا مستقیم روی پروفایل ست می‌کنیم.
        $profile = static::getContainer()->get(\App\UserProfile\Repository\UserProfileRepository::class)
            ->findByUser($secretaryUser);
        $ibans   = $profile->getIbans();
        $ibans[0]['verified'] = true;
        $profile->setBankAccount($ibans);
        $this->em->flush();

        // بدون موجودی: خطای موجودی می‌گیرد، نه خطای شبا — یعنی شبا پذیرفته شده است.
        $body = $this->authJson('POST', '/api/v1/settlement', $secretaryUser, [
            'amount_rials' => 100_000,
            'iban_id'      => $ibanId,
        ]);

        self::assertSame(422, $this->responseCode());
        self::assertSame('موجودی کافی نیست', $body['errors'][0]['message']);
    }
}
