<?php

declare(strict_types=1);

use App\Models\Coupon;
use App\Models\CouponRedemption;
use App\Models\User;
use Database\Seeders\RoleAndPermissionSeeder;
// DatabaseTransactions is applied globally in Pest.php
use Laravel\Cashier\Subscription;

// uses DatabaseTransactions from Pest.php

beforeEach(function (): void {
    $this->seed(RoleAndPermissionSeeder::class);
    $this->admin = User::factory()->admin()->create();

    $this->actingAs($this->admin);
});

test('admin can view coupon redemptions page', function (): void {
    $response = $this->get('http://admin.ezscale.dev/coupons/redemptions');

    $response->assertOk();
    $response->assertInertia(fn ($page) => $page
        ->component('Admin/Coupons/Redemptions')
        ->has('redemptions')
        ->has('coupons')
        ->has('stats')
        ->has('filters')
    );
});

test('redemptions page displays all redemptions', function (): void {
    $coupon = Coupon::factory()->create(['code' => 'TEST50']);
    $user = User::factory()->create();

    CouponRedemption::factory()
        ->for($coupon)
        ->for($user)
        ->create(['discount_amount' => '10.00']);

    CouponRedemption::factory()
        ->for($coupon)
        ->for($user)
        ->create(['discount_amount' => '15.00']);

    $response = $this->get('http://admin.ezscale.dev/coupons/redemptions');

    $response->assertOk();
    $response->assertInertia(fn ($page) => $page
        ->component('Admin/Coupons/Redemptions')
        ->where('redemptions.total', 2)
        ->where('stats.total_redemptions', 2)
        ->where('stats.total_discount', 25)
    );
});

test('redemptions can be filtered by coupon', function (): void {
    $coupon1 = Coupon::factory()->create(['code' => 'COUPON1']);
    $coupon2 = Coupon::factory()->create(['code' => 'COUPON2']);
    $user = User::factory()->create();

    CouponRedemption::factory()->for($coupon1)->for($user)->create();
    CouponRedemption::factory()->for($coupon2)->for($user)->create();
    CouponRedemption::factory()->for($coupon2)->for($user)->create();

    $response = $this->get("http://admin.ezscale.dev/coupons/redemptions?coupon_id={$coupon2->id}");

    $response->assertOk();
    $response->assertInertia(fn ($page) => $page
        ->component('Admin/Coupons/Redemptions')
        ->where('redemptions.total', 2)
        ->where('filters.coupon_id', (string) $coupon2->id)
    );
});

test('redemptions can be filtered by customer name', function (): void {
    $coupon = Coupon::factory()->create();
    $user1 = User::factory()->create(['name' => 'John Doe']);
    $user2 = User::factory()->create(['name' => 'Jane Smith']);

    CouponRedemption::factory()->for($coupon)->for($user1)->create();
    CouponRedemption::factory()->for($coupon)->for($user2)->create();

    $response = $this->get('http://admin.ezscale.dev/coupons/redemptions?customer=John');

    $response->assertOk();
    $response->assertInertia(fn ($page) => $page
        ->component('Admin/Coupons/Redemptions')
        ->where('redemptions.total', 1)
        ->where('filters.customer', 'John')
    );
});

test('redemptions can be filtered by customer email', function (): void {
    $coupon = Coupon::factory()->create();
    $user1 = User::factory()->create(['email' => 'john@example.com']);
    $user2 = User::factory()->create(['email' => 'jane@example.com']);

    CouponRedemption::factory()->for($coupon)->for($user1)->create();
    CouponRedemption::factory()->for($coupon)->for($user2)->create();

    $response = $this->get('http://admin.ezscale.dev/coupons/redemptions?customer=john@example.com');

    $response->assertOk();
    $response->assertInertia(fn ($page) => $page
        ->component('Admin/Coupons/Redemptions')
        ->where('redemptions.total', 1)
    );
});

test('redemptions can be filtered by date range', function (): void {
    $coupon = Coupon::factory()->create();
    $user = User::factory()->create();

    // Create redemptions on different dates
    CouponRedemption::factory()
        ->for($coupon)
        ->for($user)
        ->create(['created_at' => now()->subDays(10)]);

    CouponRedemption::factory()
        ->for($coupon)
        ->for($user)
        ->create(['created_at' => now()->subDays(5)]);

    CouponRedemption::factory()
        ->for($coupon)
        ->for($user)
        ->create(['created_at' => now()->subDay()]);

    $dateFrom = now()->subDays(6)->format('Y-m-d');
    $dateTo = now()->format('Y-m-d');

    $response = $this->get("http://admin.ezscale.dev/coupons/redemptions?date_from={$dateFrom}&date_to={$dateTo}");

    $response->assertOk();
    $response->assertInertia(fn ($page) => $page
        ->component('Admin/Coupons/Redemptions')
        ->where('redemptions.total', 2)
    );
});

test('redemptions page calculates correct stats', function (): void {
    $coupon1 = Coupon::factory()->create();
    $coupon2 = Coupon::factory()->create();
    $user1 = User::factory()->create();
    $user2 = User::factory()->create();
    $user3 = User::factory()->create();

    // Create multiple redemptions
    CouponRedemption::factory()->for($coupon1)->for($user1)->create(['discount_amount' => '10.00']);
    CouponRedemption::factory()->for($coupon1)->for($user2)->create(['discount_amount' => '15.00']);
    CouponRedemption::factory()->for($coupon2)->for($user3)->create(['discount_amount' => '20.00']);
    CouponRedemption::factory()->for($coupon2)->for($user1)->create(['discount_amount' => '25.00']);

    $response = $this->get('http://admin.ezscale.dev/coupons/redemptions');

    $response->assertOk();
    $response->assertInertia(fn ($page) => $page
        ->component('Admin/Coupons/Redemptions')
        ->where('stats.total_redemptions', 4)
        ->where('stats.total_discount', 70)
        ->where('stats.unique_customers', 3)
        ->where('stats.unique_coupons', 2)
    );
});

test('stats are filtered correctly when filters are applied', function (): void {
    $coupon1 = Coupon::factory()->create();
    $coupon2 = Coupon::factory()->create();
    $user1 = User::factory()->create();
    $user2 = User::factory()->create();

    CouponRedemption::factory()->for($coupon1)->for($user1)->create(['discount_amount' => '10.00']);
    CouponRedemption::factory()->for($coupon1)->for($user2)->create(['discount_amount' => '15.00']);
    CouponRedemption::factory()->for($coupon2)->for($user1)->create(['discount_amount' => '20.00']);

    $response = $this->get("http://admin.ezscale.dev/coupons/redemptions?coupon_id={$coupon1->id}");

    $response->assertOk();
    $response->assertInertia(fn ($page) => $page
        ->component('Admin/Coupons/Redemptions')
        ->where('stats.total_redemptions', 2)
        ->where('stats.total_discount', 25)
        ->where('stats.unique_customers', 2)
        ->where('stats.unique_coupons', 1)
    );
});

test('redemptions page eager loads relationships', function (): void {
    $coupon = Coupon::factory()->create();
    $user = User::factory()->create();
    $subscription = Subscription::factory()
        ->for($user)
        ->create();

    CouponRedemption::factory()
        ->for($coupon)
        ->for($user)
        ->for($subscription)
        ->create();

    $response = $this->get('http://admin.ezscale.dev/coupons/redemptions');

    $response->assertOk();
    $response->assertInertia(fn ($page) => $page
        ->component('Admin/Coupons/Redemptions')
        ->where('redemptions.data.0.coupon.code', $coupon->code)
        ->where('redemptions.data.0.user.name', $user->name)
        ->has('redemptions.data.0.subscription')
    );
});

test('redemptions are paginated correctly', function (): void {
    $coupon = Coupon::factory()->create();
    $user = User::factory()->create();

    // Create 30 redemptions
    CouponRedemption::factory()
        ->count(30)
        ->for($coupon)
        ->for($user)
        ->create();

    $response = $this->get('http://admin.ezscale.dev/coupons/redemptions');

    $response->assertOk();
    $response->assertInertia(fn ($page) => $page
        ->component('Admin/Coupons/Redemptions')
        ->where('redemptions.total', 30)
        ->where('redemptions.last_page', 2)
        ->where('redemptions.from', 1)
        ->where('redemptions.to', 25)
    );
});

test('non-admin users cannot access redemptions page', function (): void {
    $customer = User::factory()->create();
    $customer->assignRole('customer');

    $this->actingAs($customer)
        ->get('http://admin.ezscale.dev/coupons/redemptions')
        ->assertForbidden();
});

test('guests cannot access redemptions page', function (): void {
    auth()->logout();

    $this->get('http://admin.ezscale.dev/coupons/redemptions')
        ->assertRedirect();
});

test('coupons list is available for filter dropdown', function (): void {
    Coupon::factory()->create(['code' => 'ALPHA']);
    Coupon::factory()->create(['code' => 'BETA']);
    Coupon::factory()->create(['code' => 'GAMMA']);

    $response = $this->get('http://admin.ezscale.dev/coupons/redemptions');

    $response->assertOk();
    $response->assertInertia(fn ($page) => $page
        ->component('Admin/Coupons/Redemptions')
        ->has('coupons', 3)
        ->where('coupons.0.code', 'ALPHA')
        ->where('coupons.1.code', 'BETA')
        ->where('coupons.2.code', 'GAMMA')
    );
});

test('redemptions with deleted users are cascade deleted', function (): void {
    $coupon = Coupon::factory()->create();
    $user = User::factory()->create();

    $redemption = CouponRedemption::factory()
        ->for($coupon)
        ->for($user)
        ->create();

    // Delete the user (cascades to redemption)
    $user->delete();

    $response = $this->get('http://admin.ezscale.dev/coupons/redemptions');

    $response->assertOk();
    $response->assertInertia(fn ($page) => $page
        ->component('Admin/Coupons/Redemptions')
        ->where('redemptions.total', 0)
    );
});

test('redemptions can be exported to CSV', function (): void {
    $coupon = Coupon::factory()->create(['code' => 'TEST50', 'type' => 'percentage', 'value' => '50.00']);
    $user = User::factory()->create(['name' => 'John Doe', 'email' => 'john@example.com']);

    CouponRedemption::factory()
        ->for($coupon)
        ->for($user)
        ->create(['discount_amount' => '25.00']);

    $response = $this->get('http://admin.ezscale.dev/coupons/redemptions?export=csv');

    $response->assertOk();
    $response->assertHeader('Content-Type', 'text/csv; charset=UTF-8');
    $response->assertHeader('Content-Disposition');

    $content = $response->streamedContent();

    expect($content)->toContain('Redemption ID')
        ->and($content)->toContain('Coupon Code')
        ->and($content)->toContain('TEST50')
        ->and($content)->toContain('percentage')
        ->and($content)->toContain('John Doe')
        ->and($content)->toContain('john@example.com')
        ->and($content)->toContain('25.00');
});

test('CSV export respects filters', function (): void {
    $coupon1 = Coupon::factory()->create(['code' => 'COUPON1']);
    $coupon2 = Coupon::factory()->create(['code' => 'COUPON2']);
    $user = User::factory()->create();

    CouponRedemption::factory()->for($coupon1)->for($user)->create();
    CouponRedemption::factory()->for($coupon2)->for($user)->create();

    $response = $this->get("http://admin.ezscale.dev/coupons/redemptions?export=csv&coupon_id={$coupon1->id}");

    $response->assertOk();

    $content = $response->streamedContent();

    expect($content)->toContain('COUPON1')
        ->and($content)->not->toContain('COUPON2');
});
