<?php

namespace Tests\Feature;

use App\Models\User;
use App\Models\CustomerAddress;
use App\Models\Order;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Http\UploadedFile;
use Illuminate\Support\Facades\Storage;
use Tests\TestCase;

class AdminCustomerControllerTest extends TestCase
{
    use RefreshDatabase;

    public function test_authorized_admin_can_view_customers_list(): void
    {
        $admin = User::factory()->create(['role' => 'admin']);
        $customer = User::factory()->create(['role' => 'customer', 'status' => 'active']);

        $response = $this->actingAs($admin)
            ->get(route('admin.customers.index'));

        $response->assertOk()
            ->assertSee('Customer Management')
            ->assertSee('id="customersTable"', false);
    }

    public function test_admin_can_create_customer(): void
    {
        $admin = User::factory()->create(['role' => 'admin']);
        Storage::fake('public');
        $file = UploadedFile::fake()->image('profile.jpg');

        $response = $this->actingAs($admin)
            ->post(route('admin.customers.store'), [
                'name' => 'John Doe',
                'email' => 'john@example.com',
                'phone' => '099999999',
                'gender' => 'male',
                'dob' => '1995-05-15',
                'customer_group' => 'General',
                'status' => 'active',
                'password' => 'password123',
                'password_confirmation' => 'password123',
                'profile_image' => $file,
            ]);

        $response->assertRedirect(route('admin.customers.index'));
        
        $this->assertDatabaseHas('users', [
            'name' => 'John Doe',
            'email' => 'john@example.com',
            'role' => 'customer',
            'gender' => 'male',
            'customer_group' => 'General',
            'status' => 'active',
        ]);

        $user = User::where('email', 'john@example.com')->first();
        $this->assertEquals('1995-05-15', $user->dob->format('Y-m-d'));
        $this->assertNotNull($user->profile_image);
        Storage::disk('public')->assertExists($user->profile_image);
    }

    public function test_admin_can_edit_and_update_customer(): void
    {
        $admin = User::factory()->create(['role' => 'admin']);
        $customer = User::factory()->create([
            'role' => 'customer',
            'name' => 'Old Name',
            'email' => 'old@example.com',
            'customer_group' => 'General',
            'status' => 'active',
        ]);

        $response = $this->actingAs($admin)
            ->put(route('admin.customers.update', $customer->id), [
                'name' => 'New Name',
                'email' => 'new@example.com',
                'customer_group' => 'VIP',
                'status' => 'suspended',
            ]);

        $response->assertRedirect(route('admin.customers.index'));
        
        $this->assertDatabaseHas('users', [
            'id' => $customer->id,
            'name' => 'New Name',
            'email' => 'new@example.com',
            'customer_group' => 'VIP',
            'status' => 'suspended',
        ]);
    }

    public function test_admin_can_toggle_customer_status(): void
    {
        $admin = User::factory()->create(['role' => 'admin']);
        $customer = User::factory()->create([
            'role' => 'customer',
            'status' => 'active',
        ]);

        $response = $this->actingAs($admin)
            ->post(route('admin.customers.toggle-status', $customer->id));

        $response->assertRedirect();
        $this->assertEquals('suspended', $customer->fresh()->status);

        $response2 = $this->actingAs($admin)
            ->post(route('admin.customers.toggle-status', $customer->id));

        $response2->assertRedirect();
        $this->assertEquals('active', $customer->fresh()->status);
    }

    public function test_admin_can_delete_customer(): void
    {
        $admin = User::factory()->create(['role' => 'admin']);
        $customer = User::factory()->create([
            'role' => 'customer',
        ]);

        $response = $this->actingAs($admin)
            ->delete(route('admin.customers.destroy', $customer->id));

        $response->assertRedirect(route('admin.customers.index'));
        $this->assertDatabaseMissing('users', ['id' => $customer->id]);
    }

    public function test_admin_can_export_customers_csv(): void
    {
        $admin = User::factory()->create(['role' => 'admin']);
        User::factory()->create(['role' => 'customer', 'name' => 'Alice']);
        User::factory()->create(['role' => 'customer', 'name' => 'Bob']);

        $response = $this->actingAs($admin)
            ->get(route('admin.customers.export', ['status' => 'active']));

        $response->assertOk();
        $response->assertHeader('Content-Type', 'text/csv; charset=UTF-8');
        $this->assertStringContainsString('Alice', $response->streamedContent());
        $this->assertStringContainsString('Bob', $response->streamedContent());
    }

    public function test_admin_can_create_and_manage_customer_addresses(): void
    {
        $admin = User::factory()->create(['role' => 'admin']);
        $customer = User::factory()->create(['role' => 'customer']);

        // 1. Add Address
        $responseAdd = $this->actingAs($admin)
            ->post(route('admin.customers.addresses.store', $customer->id), [
                'label' => 'Home',
                'recipient_name' => 'Jane Recipient',
                'phone' => '012345678',
                'country' => 'Cambodia',
                'province' => 'Phnom Penh',
                'city' => 'Phnom Penh',
                'street_address' => 'Street 101',
                'is_default_shipping' => '1',
                'is_default_billing' => '1',
            ]);

        $responseAdd->assertRedirect();
        
        $this->assertDatabaseHas('customer_addresses', [
            'user_id' => $customer->id,
            'label' => 'Home',
            'recipient_name' => 'Jane Recipient',
            'is_default_shipping' => 1,
            'is_default_billing' => 1,
        ]);

        $address = CustomerAddress::first();

        // 2. Set Default
        $address2 = CustomerAddress::create([
            'user_id' => $customer->id,
            'label' => 'Office',
            'recipient_name' => 'Jane Office',
            'phone' => '012345678',
            'country' => 'Cambodia',
            'province' => 'Phnom Penh',
            'city' => 'Phnom Penh',
            'street_address' => 'Street 202',
            'is_default_shipping' => false,
            'is_default_billing' => false,
        ]);

        $responseSetDefault = $this->actingAs($admin)
            ->post(route('admin.customers.addresses.set-default', [$customer->id, $address2->id, 'shipping']));

        $responseSetDefault->assertRedirect();
        $this->assertTrue((bool)$address2->fresh()->is_default_shipping);
        $this->assertFalse((bool)$address->fresh()->is_default_shipping);

        // 3. Update Address
        $responseUpdate = $this->actingAs($admin)
            ->put(route('admin.customers.addresses.update', [$customer->id, $address->id]), [
                'label' => 'Home Sweet Home',
                'recipient_name' => 'Jane Recipient Updated',
                'phone' => '012345678',
                'country' => 'Cambodia',
                'province' => 'Phnom Penh',
                'city' => 'Phnom Penh',
                'street_address' => 'Street 101 Updated',
            ]);

        $responseUpdate->assertRedirect();
        $this->assertEquals('Home Sweet Home', $address->fresh()->label);

        // 4. Delete Address
        $responseDelete = $this->actingAs($admin)
            ->delete(route('admin.customers.addresses.destroy', [$customer->id, $address->id]));

        $responseDelete->assertRedirect();
        $this->assertDatabaseMissing('customer_addresses', ['id' => $address->id]);
    }

    public function test_unauthorized_staff_cannot_manage_customers(): void
    {
        $this->seed(\Database\Seeders\PermissionSeeder::class);
        $staff = User::factory()->create(['role' => 'admin']);
        $staff->assignRole('Staff');
        $customer = User::factory()->create(['role' => 'customer']);

        $this->actingAs($staff)
            ->post(route('admin.customers.toggle-status', $customer->id))
            ->assertStatus(403);
    }
}
