<?php

declare(strict_types=1);

use App\Models\PricingTier;
use Database\Seeders\PricingTierSeeder;
use Illuminate\Foundation\Testing\DatabaseTransactions;
use Illuminate\Support\Carbon;
use Illuminate\Support\Facades\DB;

uses(DatabaseTransactions::class);

beforeEach(function () {
    $this->seed(PricingTierSeeder::class);
});

it('GET /api/admin/pricing-tiers returns active + scheduled sets', function () {
    $response = $this->getJson('/api/admin/pricing-tiers');
    $response->assertOk();
    expect($response->json('data.active'))->toHaveCount(7);
});

it('POST creates 7 new tiers with auto effective_from = 1st of next month', function () {
    $payload = ['tiers' => [
        ['tier_no' => 1, 'leads_in_tier' => 50,   'price_rub' => '600.00'],
        ['tier_no' => 2, 'leads_in_tier' => 150,  'price_rub' => '550.00'],
        ['tier_no' => 3, 'leads_in_tier' => 300,  'price_rub' => '500.00'],
        ['tier_no' => 4, 'leads_in_tier' => 700,  'price_rub' => '450.00'],
        ['tier_no' => 5, 'leads_in_tier' => 1500, 'price_rub' => '400.00'],
        ['tier_no' => 6, 'leads_in_tier' => 3000, 'price_rub' => '350.00'],
        ['tier_no' => 7, 'leads_in_tier' => null, 'price_rub' => '300.00'],
    ]];
    $this->postJson('/api/admin/pricing-tiers', $payload)->assertCreated();

    $expectedDate = now('Europe/Moscow')->startOfMonth()->addMonth()->toDateString();
    $newTiers = PricingTier::where('effective_from', $expectedDate)->get();
    expect($newTiers)->toHaveCount(7);
    expect($newTiers->where('tier_no', 1)->first()->price_per_lead_kopecks)->toBe(60000);
    expect($newTiers->where('tier_no', 7)->first()->leads_in_tier)->toBeNull();
});

it('POST validates: exactly 7 rows required', function () {
    $this->postJson('/api/admin/pricing-tiers', ['tiers' => [
        ['tier_no' => 1, 'leads_in_tier' => 50, 'price_rub' => '600.00'],
    ]])->assertStatus(422);
});

it('POST validates: tier_no must be unique 1..7', function () {
    $this->postJson('/api/admin/pricing-tiers', ['tiers' => [
        ['tier_no' => 1, 'leads_in_tier' => 50,   'price_rub' => '600.00'],
        ['tier_no' => 1, 'leads_in_tier' => 150,  'price_rub' => '550.00'],
        ['tier_no' => 3, 'leads_in_tier' => 300,  'price_rub' => '500.00'],
        ['tier_no' => 4, 'leads_in_tier' => 700,  'price_rub' => '450.00'],
        ['tier_no' => 5, 'leads_in_tier' => 1500, 'price_rub' => '400.00'],
        ['tier_no' => 6, 'leads_in_tier' => 3000, 'price_rub' => '350.00'],
        ['tier_no' => 7, 'leads_in_tier' => null, 'price_rub' => '300.00'],
    ]])->assertStatus(422);
});

it('POST validates: tier 7 leads_in_tier must be null', function () {
    $this->postJson('/api/admin/pricing-tiers', ['tiers' => [
        ['tier_no' => 1, 'leads_in_tier' => 50,    'price_rub' => '600.00'],
        ['tier_no' => 2, 'leads_in_tier' => 150,   'price_rub' => '550.00'],
        ['tier_no' => 3, 'leads_in_tier' => 300,   'price_rub' => '500.00'],
        ['tier_no' => 4, 'leads_in_tier' => 700,   'price_rub' => '450.00'],
        ['tier_no' => 5, 'leads_in_tier' => 1500,  'price_rub' => '400.00'],
        ['tier_no' => 6, 'leads_in_tier' => 3000,  'price_rub' => '350.00'],
        ['tier_no' => 7, 'leads_in_tier' => 99999, 'price_rub' => '300.00'],
    ]])->assertStatus(422);
});

it('POST validates: price_rub >= 0', function () {
    $this->postJson('/api/admin/pricing-tiers', ['tiers' => [
        ['tier_no' => 1, 'leads_in_tier' => 50,   'price_rub' => '-1.00'],
        ['tier_no' => 2, 'leads_in_tier' => 150,  'price_rub' => '550.00'],
        ['tier_no' => 3, 'leads_in_tier' => 300,  'price_rub' => '500.00'],
        ['tier_no' => 4, 'leads_in_tier' => 700,  'price_rub' => '450.00'],
        ['tier_no' => 5, 'leads_in_tier' => 1500, 'price_rub' => '400.00'],
        ['tier_no' => 6, 'leads_in_tier' => 3000, 'price_rub' => '350.00'],
        ['tier_no' => 7, 'leads_in_tier' => null, 'price_rub' => '300.00'],
    ]])->assertStatus(422);
});

it('DELETE /scheduled/{effective_from} removes future tiers only', function () {
    $futureDate = now('Europe/Moscow')->addMonth()->startOfMonth()->toDateString();
    PricingTier::factory()->count(7)->sequence(fn ($s) => ['tier_no' => $s->index + 1])
        ->create(['effective_from' => $futureDate, 'is_active' => true]);

    $this->deleteJson("/api/admin/pricing-tiers/scheduled/{$futureDate}")->assertOk();

    expect(PricingTier::where('effective_from', $futureDate)->count())->toBe(0);
    expect(PricingTier::where('effective_from', '1970-01-01')->count())->toBe(7);
});

it('store accepts a custom effective_from date', function (): void {
    $custom = Carbon::now('Europe/Moscow')->addMonths(3)->toDateString();

    $response = $this->postJson('/api/admin/pricing-tiers', [
        'tiers' => [
            ['tier_no' => 1, 'leads_in_tier' => 50,   'price_rub' => '600.00'],
            ['tier_no' => 2, 'leads_in_tier' => 150,  'price_rub' => '550.00'],
            ['tier_no' => 3, 'leads_in_tier' => 300,  'price_rub' => '500.00'],
            ['tier_no' => 4, 'leads_in_tier' => 700,  'price_rub' => '450.00'],
            ['tier_no' => 5, 'leads_in_tier' => 1500, 'price_rub' => '400.00'],
            ['tier_no' => 6, 'leads_in_tier' => 3000, 'price_rub' => '350.00'],
            ['tier_no' => 7, 'leads_in_tier' => null, 'price_rub' => '300.00'],
        ],
        'effective_from' => $custom,
    ]);

    $response->assertCreated()->assertJson(['effective_from' => $custom]);
    expect(PricingTier::where('effective_from', $custom)->count())->toBe(7);
});

it('store принимает effective_from равную сегодня (по запросу владельца)', function (): void {
    // Раньше today отвергался (after:today). Владелец попросил разрешить смену
    // тарифа текущей датой → after_or_equal:today. Прошлое по-прежнему 422.
    $today = Carbon::now('Europe/Moscow')->toDateString();

    $this->postJson('/api/admin/pricing-tiers', [
        'tiers' => [
            ['tier_no' => 1, 'leads_in_tier' => 50,   'price_rub' => '600.00'],
            ['tier_no' => 2, 'leads_in_tier' => 150,  'price_rub' => '550.00'],
            ['tier_no' => 3, 'leads_in_tier' => 300,  'price_rub' => '500.00'],
            ['tier_no' => 4, 'leads_in_tier' => 700,  'price_rub' => '450.00'],
            ['tier_no' => 5, 'leads_in_tier' => 1500, 'price_rub' => '400.00'],
            ['tier_no' => 6, 'leads_in_tier' => 3000, 'price_rub' => '350.00'],
            ['tier_no' => 7, 'leads_in_tier' => null, 'price_rub' => '300.00'],
        ],
        'effective_from' => $today,
    ])->assertCreated()->assertJson(['effective_from' => $today]);

    expect(PricingTier::where('effective_from', $today)->count())->toBe(7);
});

it('store берёт audit admin_user_id из config и не трогает saas_admin_users', function (): void {
    // Прод-баг: рантайм-роль crm_app_user не имеет прав на saas_admin_users →
    // resolveAdminUserId падал «permission denied» → 500 на ВСЕХ admin-сохранениях.
    // Фикс: при config('admin.audit_system_user_id') брать id оттуда, не обращаясь
    // к saas_admin_users (на dev/test суперюзер — fallback на старую логику).
    $adminId = DB::table('saas_admin_users')->insertGetId([
        'email' => 'cfg-admin@liderra.local', 'full_name' => 'Cfg Admin',
        'password_hash' => 'stub', 'role' => 'super_admin',
        'is_active' => false, 'sso_provider' => 'local', 'is_break_glass' => false,
    ]);
    config(['admin.audit_system_user_id' => $adminId]);
    $countBefore = DB::table('saas_admin_users')->count();

    $this->postJson('/api/admin/pricing-tiers', ['tiers' => [
        ['tier_no' => 1, 'leads_in_tier' => 50,   'price_rub' => '600.00'],
        ['tier_no' => 2, 'leads_in_tier' => 150,  'price_rub' => '550.00'],
        ['tier_no' => 3, 'leads_in_tier' => 300,  'price_rub' => '500.00'],
        ['tier_no' => 4, 'leads_in_tier' => 700,  'price_rub' => '450.00'],
        ['tier_no' => 5, 'leads_in_tier' => 1500, 'price_rub' => '400.00'],
        ['tier_no' => 6, 'leads_in_tier' => 3000, 'price_rub' => '350.00'],
        ['tier_no' => 7, 'leads_in_tier' => null, 'price_rub' => '300.00'],
    ]])->assertCreated();

    $log = DB::table('saas_admin_audit_log')
        ->where('action', 'pricing_tiers.create_scheduled')->latest('id')->first();
    expect((int) $log->admin_user_id)->toBe($adminId);
    // стаб system-pricing НЕ создан — saas_admin_users не трогали.
    expect(DB::table('saas_admin_users')->count())->toBe($countBefore);
});

it('store rejects effective_from in the past', function (): void {
    $past = Carbon::now('Europe/Moscow')->subDay()->toDateString();

    $this->postJson('/api/admin/pricing-tiers', [
        'tiers' => [
            ['tier_no' => 1, 'leads_in_tier' => 50,   'price_rub' => '600.00'],
            ['tier_no' => 2, 'leads_in_tier' => 150,  'price_rub' => '550.00'],
            ['tier_no' => 3, 'leads_in_tier' => 300,  'price_rub' => '500.00'],
            ['tier_no' => 4, 'leads_in_tier' => 700,  'price_rub' => '450.00'],
            ['tier_no' => 5, 'leads_in_tier' => 1500, 'price_rub' => '400.00'],
            ['tier_no' => 6, 'leads_in_tier' => 3000, 'price_rub' => '350.00'],
            ['tier_no' => 7, 'leads_in_tier' => null, 'price_rub' => '300.00'],
        ],
        'effective_from' => $past,
    ])->assertStatus(422);
});

it('writes audit-trail row in saas_admin_audit_log on POST', function () {
    $this->postJson('/api/admin/pricing-tiers', ['tiers' => [
        ['tier_no' => 1, 'leads_in_tier' => 50,   'price_rub' => '600.00'],
        ['tier_no' => 2, 'leads_in_tier' => 150,  'price_rub' => '550.00'],
        ['tier_no' => 3, 'leads_in_tier' => 300,  'price_rub' => '500.00'],
        ['tier_no' => 4, 'leads_in_tier' => 700,  'price_rub' => '450.00'],
        ['tier_no' => 5, 'leads_in_tier' => 1500, 'price_rub' => '400.00'],
        ['tier_no' => 6, 'leads_in_tier' => 3000, 'price_rub' => '350.00'],
        ['tier_no' => 7, 'leads_in_tier' => null, 'price_rub' => '300.00'],
    ]])->assertCreated();

    $log = DB::table('saas_admin_audit_log')
        ->where('action', 'pricing_tiers.create_scheduled')->first();
    expect($log)->not->toBeNull();
});

test('AdminPricingTiers::store сохраняет цену 10.10 ₽ как ровно 1010 kopecks (без float-drift)', function () {
    $tiers = [];
    for ($i = 1; $i <= 6; $i++) {
        $tiers[] = ['tier_no' => $i, 'leads_in_tier' => 50, 'price_rub' => '10.10'];
    }
    $tiers[] = ['tier_no' => 7, 'leads_in_tier' => null, 'price_rub' => '10.10'];

    $resp = $this->postJson('/api/admin/pricing-tiers', ['tiers' => $tiers]);
    $resp->assertCreated();

    $expectedDate = now('Europe/Moscow')->startOfMonth()->addMonth()->toDateString();
    foreach (PricingTier::query()->where('effective_from', $expectedDate)->orderBy('tier_no')->get() as $row) {
        expect((int) $row->price_per_lead_kopecks)->toBe(1010);
    }
});

test('AdminPricingTiers::store отклоняет некорректный price_rub (например "10.123" — три знака после точки)', function () {
    $tiers = [];
    for ($i = 1; $i <= 6; $i++) {
        $tiers[] = ['tier_no' => $i, 'leads_in_tier' => 50, 'price_rub' => '10.10'];
    }
    $tiers[] = ['tier_no' => 7, 'leads_in_tier' => null, 'price_rub' => '10.123'];

    $resp = $this->postJson('/api/admin/pricing-tiers', ['tiers' => $tiers]);
    $resp->assertStatus(422);
    $resp->assertJsonValidationErrors(['tiers.6.price_rub']);
});
