<?php

declare(strict_types=1);

use App\Models\Tenant;
use Illuminate\Foundation\Testing\DatabaseTransactions;
use Illuminate\Support\Facades\DB;

uses(DatabaseTransactions::class);

beforeEach(function () {
    // Чистим всё что было в seed/предыдущих тестах — для чистых счётчиков stats.
    DB::table('tenants')->delete();
});

test('GET /api/admin/tenants возвращает 200 и пустой список без данных', function () {
    $r = $this->getJson('/api/admin/tenants');

    $r->assertStatus(200);
    expect($r->json('tenants'))->toBe([]);
    expect($r->json('total'))->toBe(0);
    expect($r->json('limit'))->toBe(100);
    expect($r->json('offset'))->toBe(0);
});

test('GET /api/admin/tenants возвращает все поля', function () {
    $tenant = Tenant::factory()->create([
        'subdomain' => 'okna-msk',
        'organization_name' => 'Окна Москва',
        'contact_email' => 'admin@okna-msk.test',
        'balance_rub' => '15000.00',
        'balance_leads' => 287,
        'is_trial' => false,
        'desired_daily_numbers' => 12,
    ]);

    $r = $this->getJson('/api/admin/tenants');

    $r->assertStatus(200);
    expect($r->json('total'))->toBe(1);
    $row = $r->json('tenants.0');
    expect($row['id'])->toBe($tenant->id);
    expect($row['subdomain'])->toBe('okna-msk');
    expect($row['organization_name'])->toBe('Окна Москва');
    expect($row['contact_email'])->toBe('admin@okna-msk.test');
    expect($row['balance_rub'])->toBe('15000.00');
    expect($row['balance_leads'])->toBe(287);
    expect($row['is_trial'])->toBeFalse();
    expect($row['desired_daily_numbers'])->toBe(12);
});

test('GET /api/admin/tenants фильтрует по status', function () {
    Tenant::factory()->create(['status' => 'active', 'organization_name' => 'A']);
    Tenant::factory()->create(['status' => 'suspended', 'organization_name' => 'B']);
    Tenant::factory()->create(['status' => 'active', 'organization_name' => 'C']);

    $r = $this->getJson('/api/admin/tenants?status=active');

    expect($r->json('total'))->toBe(2);
    $names = collect($r->json('tenants'))->pluck('organization_name')->all();
    expect($names)->toContain('A');
    expect($names)->toContain('C');
    expect($names)->not->toContain('B');
});

test('GET /api/admin/tenants фильтрует по search (organization_name + subdomain + email ILIKE)', function () {
    Tenant::factory()->create(['organization_name' => 'Окна Москва', 'subdomain' => 'okna']);
    Tenant::factory()->create(['organization_name' => 'Двери СПб', 'subdomain' => 'dveri']);

    expect($this->getJson('/api/admin/tenants?search=окна')->json('total'))->toBe(1);
    expect($this->getJson('/api/admin/tenants?search=DVERI')->json('total'))->toBe(1);
    expect($this->getJson('/api/admin/tenants?search=что-то-несуществующее')->json('total'))->toBe(0);
});

test('GET /api/admin/tenants сортирует по last_activity_at DESC', function () {
    $oldest = Tenant::factory()->create([
        'organization_name' => 'oldest',
        'last_activity_at' => now()->subDays(5),
    ]);
    $newest = Tenant::factory()->create([
        'organization_name' => 'newest',
        'last_activity_at' => now()->subMinutes(5),
    ]);
    $middle = Tenant::factory()->create([
        'organization_name' => 'middle',
        'last_activity_at' => now()->subDays(1),
    ]);

    $r = $this->getJson('/api/admin/tenants');
    $names = collect($r->json('tenants'))->pluck('organization_name')->all();
    expect($names[0])->toBe('newest');
    expect($names[1])->toBe('middle');
    expect($names[2])->toBe('oldest');
});

test('GET /api/admin/tenants возвращает stats (total/active/trial/overdue)', function () {
    Tenant::factory()->create(['status' => 'active', 'is_trial' => false, 'balance_rub' => '100']);
    Tenant::factory()->create(['status' => 'active', 'is_trial' => true, 'balance_rub' => '50']);
    Tenant::factory()->create(['status' => 'suspended', 'is_trial' => false, 'balance_rub' => '-200']);
    Tenant::factory()->create(['status' => 'active', 'is_trial' => false, 'chargeback_unrecovered_rub' => '500']);

    $r = $this->getJson('/api/admin/tenants');

    expect($r->json('stats.total'))->toBe(4);
    expect($r->json('stats.active'))->toBe(3);
    expect($r->json('stats.trial'))->toBe(1);
    expect($r->json('stats.overdue'))->toBe(2); // отрицательный balance + chargeback
});

test('GET /api/admin/tenants soft-deleted tenant НЕ возвращается', function () {
    $deleted = Tenant::factory()->create(['organization_name' => 'удалён']);
    $deleted->delete(); // soft-delete

    Tenant::factory()->create(['organization_name' => 'жив']);

    $r = $this->getJson('/api/admin/tenants');

    expect($r->json('total'))->toBe(1);
    expect($r->json('tenants.0.organization_name'))->toBe('жив');
});

test('GET /api/admin/tenants возвращает mrr_rub для активного тарифа (не-trial)', function () {
    $tariffId = (int) DB::table('tariff_plans')->insertGetId([
        'code' => 'tp_'.bin2hex(random_bytes(4)),
        'name' => 'Команда',
        'billing_model' => 'monthly',
        'price_monthly' => 990.00,
        'is_active' => true,
        'is_public' => true,
        'sort_order' => 1,
        'created_at' => now(),
    ]);

    $tenant = Tenant::factory()->create([
        'organization_name' => 'Окна',
        'is_trial' => false,
    ]);
    DB::table('tenants')->where('id', $tenant->id)->update(['current_tariff_id' => $tariffId]);

    $r = $this->getJson('/api/admin/tenants');
    expect($r->json('tenants.0.mrr_rub'))->toBe('990.00');
});

test('GET /api/admin/tenants mrr_rub=null для trial', function () {
    $tariffId = (int) DB::table('tariff_plans')->insertGetId([
        'code' => 'tp_'.bin2hex(random_bytes(4)),
        'name' => 'Команда',
        'billing_model' => 'monthly',
        'price_monthly' => 990.00,
        'is_active' => true,
        'is_public' => true,
        'sort_order' => 1,
        'created_at' => now(),
    ]);

    $tenant = Tenant::factory()->create([
        'organization_name' => 'Trial',
        'is_trial' => true,
    ]);
    DB::table('tenants')->where('id', $tenant->id)->update(['current_tariff_id' => $tariffId]);

    $r = $this->getJson('/api/admin/tenants');
    expect($r->json('tenants.0.mrr_rub'))->toBeNull();
});

test('GET /api/admin/tenants mrr_rub=null если current_tariff_id отсутствует', function () {
    Tenant::factory()->create(['organization_name' => 'NoTariff', 'current_tariff_id' => null]);

    $r = $this->getJson('/api/admin/tenants');
    expect($r->json('tenants.0.mrr_rub'))->toBeNull();
});

test('GET /api/admin/tenants фильтрует по statuses (производный статус, multi)', function () {
    // active: не trial, status=active, balance>=0, chargeback=0
    Tenant::factory()->create(['organization_name' => 'AC', 'status' => 'active', 'is_trial' => false, 'balance_rub' => '100', 'chargeback_unrecovered_rub' => '0']);
    // trial: is_trial=true (приоритет выше всех)
    Tenant::factory()->create(['organization_name' => 'TR', 'status' => 'active', 'is_trial' => true, 'balance_rub' => '0']);
    // overdue: не trial, balance<0
    Tenant::factory()->create(['organization_name' => 'OV', 'status' => 'active', 'is_trial' => false, 'balance_rub' => '-50', 'chargeback_unrecovered_rub' => '0']);
    // suspended: status=suspended
    Tenant::factory()->create(['organization_name' => 'SU', 'status' => 'suspended', 'is_trial' => false, 'balance_rub' => '100', 'chargeback_unrecovered_rub' => '0']);

    $r = $this->getJson('/api/admin/tenants?statuses=overdue,trial');

    $names = collect($r->json('tenants'))->pluck('organization_name')->all();
    expect($r->json('total'))->toBe(2);
    expect($names)->toContain('TR');
    expect($names)->toContain('OV');
    expect($names)->not->toContain('AC');
    expect($names)->not->toContain('SU');
});

test('GET /api/admin/tenants фильтрует по tariffs (имя тарифа, multi)', function () {
    $mk = fn (string $name): int => (int) DB::table('tariff_plans')->insertGetId([
        'code' => 'tp_'.bin2hex(random_bytes(4)),
        'name' => $name,
        'billing_model' => 'monthly',
        'price_monthly' => 990.00,
        'is_active' => true,
        'is_public' => true,
        'sort_order' => 1,
        'created_at' => now(),
    ]);
    $proId = $mk('Pro');
    $teamId = $mk('Команда');

    $p = Tenant::factory()->create(['organization_name' => 'P1']);
    DB::table('tenants')->where('id', $p->id)->update(['current_tariff_id' => $proId]);
    $k = Tenant::factory()->create(['organization_name' => 'K1']);
    DB::table('tenants')->where('id', $k->id)->update(['current_tariff_id' => $teamId]);

    $r = $this->getJson('/api/admin/tenants?tariffs=Pro');

    expect($r->json('total'))->toBe(1);
    expect($r->json('tenants.0.organization_name'))->toBe('P1');
});

test('GET /api/admin/tenants поддерживает limit + offset', function () {
    foreach (range(1, 5) as $i) {
        Tenant::factory()->create([
            'organization_name' => 'T'.$i,
            'last_activity_at' => now()->subMinutes($i),
        ]);
    }

    $r = $this->getJson('/api/admin/tenants?limit=2&offset=1');
    expect($r->json('total'))->toBe(5);
    expect($r->json('limit'))->toBe(2);
    expect($r->json('offset'))->toBe(1);
    expect(count($r->json('tenants')))->toBe(2);
});
