<?php

namespace App\Tests\Category;

use App\Tests\ApiTestCase;
use Doctrine\DBAL\Connection;

/**
 * POST /api/v1/admin/categories/{bundle}/import — bulk wipe+replace import.
 *
 * Guards the two behaviours the feature promises:
 *  - strict validation: an invalid file is rejected whole, the table is untouched;
 *  - referential integrity: self/cross references must resolve before any write.
 *
 * Runs against db_test (never reset), so every assertion is made against the
 * table the import owns, and the destructive cases verify the row count is the
 * SAME before and after a rejected import.
 */
class CategoryImportTest extends ApiTestCase
{
    private function db(): Connection
    {
        return static::getContainer()->get(Connection::class);
    }

    private function rowCount(string $table): int
    {
        return (int) $this->db()->fetchOne('SELECT COUNT(*) FROM ' . $table);
    }

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

        $body = $this->authJson('POST', '/api/v1/admin/categories/tags/import', $admin, [
            ['id' => 90001, 'name' => 'تگ یک', 'slug' => 'imp-tag-1', 'status' => 1],
            ['id' => 90002, 'name' => 'تگ دو', 'slug' => 'imp-tag-2', 'status' => 0],
        ]);

        $this->assertSame(200, $this->responseCode());
        $this->assertSame(2, $body['data']['imported'] ?? null);
        // wipe+replace: the table now holds exactly the imported rows
        $this->assertSame(2, $this->rowCount('tags'));
        $this->assertSame('imp-tag-1', $this->db()->fetchOne('SELECT slug FROM tags WHERE id = 90001'));
    }

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

        // seed a known state, then attempt a bad import — count must not change
        $this->authJson('POST', '/api/v1/admin/categories/tags/import', $admin, [
            ['id' => 91001, 'name' => 'پایه', 'slug' => 'seed-tag', 'status' => 1],
        ]);
        $before = $this->rowCount('tags');

        $body = $this->authJson('POST', '/api/v1/admin/categories/tags/import', $admin, [
            ['id' => 1, 'name' => 'خوب', 'slug' => 'ok', 'status' => 1],
            ['id' => 1, 'name' => '', 'slug' => 'ok', 'status' => 9], // dup id, empty name, dup slug, bad status
        ]);

        $this->assertSame(422, $this->responseCode());
        $this->assertNotEmpty($body['errors']);
        $this->assertSame($before, $this->rowCount('tags'));   // table untouched
    }

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

        $body = $this->authJson('POST', '/api/v1/admin/categories/specialties/import', $admin, [
            ['id' => 1, 'name' => 'ریشه', 'slug' => 'imp-root', 'status' => 1, 'weight' => 0, 'parent_id' => null],
            ['id' => 2, 'name' => 'فرزند', 'slug' => 'imp-child', 'status' => 1, 'weight' => 0, 'parent_id' => 9999],
        ]);

        $this->assertSame(422, $this->responseCode());
        $fields = array_column($body['errors'], 'field');
        $this->assertContains('parent_id', $fields);
    }

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

        $this->authJson('POST', '/api/v1/admin/categories/cities/import', $admin, [
            [
                'id' => 95001, 'name' => 'شهر تست', 'status' => 1, 'weight' => 0,
                'site_name' => 'تست نوبت',
                'title' => 'نوبت‌دهی آنلاین پزشکان شهر تست | تست نوبت',
                'slogan' => 'شعار تست',
                'keywords' => 'کلمه یک, کلمه دو',
                'province_id' => null,
                'social_media' => ['instagram' => 'test_nobat'],
            ],
        ]);
        $this->assertSame(200, $this->responseCode());
        $this->assertSame(
            'نوبت‌دهی آنلاین پزشکان شهر تست | تست نوبت',
            $this->db()->fetchOne('SELECT title FROM cities WHERE id = 95001'),
        );

        // export must round-trip lossless in the shape nobat724_front/data/city.json uses
        $body = $this->authJson('GET', '/api/v1/admin/categories/cities/export', $admin);
        $row = null;
        foreach ($body['data'] as $r) {
            if (($r['id'] ?? null) === 95001) { $row = $r; break; }
        }
        $this->assertNotNull($row);
        $this->assertSame('نوبت‌دهی آنلاین پزشکان شهر تست | تست نوبت', $row['title']);
        $this->assertSame(['instagram' => 'test_nobat'], $row['social_media']);
        $this->assertArrayHasKey('province_name', $row);
    }

    public function testNonAdminIsForbidden(): void
    {
        $user = $this->createUser(['ROLE_USER']);
        $this->authJson('POST', '/api/v1/admin/categories/tags/import', $user, [
            ['id' => 1, 'name' => 'x', 'slug' => 'x', 'status' => 1],
        ]);
        $this->assertSame(403, $this->responseCode());
    }

    public function testUnknownBundleIs404(): void
    {
        $admin = $this->createUser(['ROLE_ADMIN']);
        $this->authJson('POST', '/api/v1/admin/categories/nope/import', $admin, [
            ['id' => 1, 'name' => 'x', 'slug' => 'x', 'status' => 1],
        ]);
        $this->assertSame(404, $this->responseCode());
    }
}
