<?php

namespace Tests\Feature;

use App\Models\Category;
use App\Models\Customer;
use App\Models\Product;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Support\Facades\Hash;
use Tests\TestCase;

class CustomerCartFavoriteTest extends TestCase
{
    use RefreshDatabase;

    public function test_customer_can_add_update_and_remove_cart_item(): void
    {
        $customer = $this->customer();
        $product = $this->product(stock: 5);

        $this->actingAs($customer, 'customer')
            ->post("/cart/{$product->id}", ['quantity' => 2])
            ->assertSessionHas('status');

        $item = $customer->cartItems()->firstOrFail();
        $this->assertSame(2, $item->quantity);

        $this->actingAs($customer, 'customer')
            ->patch("/cart/items/{$item->id}", ['quantity' => 4])
            ->assertSessionHas('status');

        $this->assertSame(4, $item->fresh()->quantity);

        $this->actingAs($customer, 'customer')
            ->delete("/cart/items/{$item->id}")
            ->assertSessionHas('status');

        $this->assertDatabaseMissing('customer_cart_items', ['id' => $item->id]);
    }

    public function test_customer_can_add_product_variant_to_cart(): void
    {
        $customer = $this->customer();
        $product = $this->product(stock: 20);
        $variant = $product->variants()->create([
            'name' => 'Color',
            'value' => 'Black',
            'price' => 120,
            'stock' => 3,
            'is_active' => true,
        ]);

        $this->actingAs($customer, 'customer')
            ->post("/cart/{$product->id}", [
                'product_variant_id' => $variant->id,
                'quantity' => 5,
            ])
            ->assertSessionHas('status');

        $item = $customer->cartItems()->with('variant')->firstOrFail();

        $this->assertSame($variant->id, $item->product_variant_id);
        $this->assertSame(3, $item->quantity);
        $this->assertSame(120.0, $item->unitPrice());

        $this->actingAs($customer, 'customer')
            ->get('/cart')
            ->assertOk()
            ->assertSee('Color: Black')
            ->assertSee('Rs 120');
    }

    public function test_cart_uses_real_discounted_product_price(): void
    {
        $customer = $this->customer();
        $product = $this->product(stock: 5);
        $product->update(['price' => 100, 'discount_percent' => 10]);

        $this->actingAs($customer, 'customer')
            ->post("/cart/{$product->id}", ['quantity' => 2])
            ->assertSessionHas('status');

        $item = $customer->cartItems()->with('product')->firstOrFail();

        $this->assertSame(90.0, $item->unitPrice());

        $this->actingAs($customer, 'customer')
            ->get('/cart')
            ->assertOk()
            ->assertSee('Rs 90')
            ->assertSee('Rs 180');
    }

    public function test_customer_can_toggle_favorite(): void
    {
        $customer = $this->customer();
        $product = $this->product();

        $this->actingAs($customer, 'customer')
            ->post("/favorites/{$product->id}")
            ->assertSessionHas('status');

        $this->assertDatabaseHas('customer_favorites', [
            'customer_id' => $customer->id,
            'product_id' => $product->id,
        ]);

        $this->actingAs($customer, 'customer')
            ->post("/favorites/{$product->id}")
            ->assertSessionHas('status');

        $this->assertDatabaseMissing('customer_favorites', [
            'customer_id' => $customer->id,
            'product_id' => $product->id,
        ]);
    }

    public function test_guest_is_redirected_to_login_when_adding_to_cart(): void
    {
        $product = $this->product();

        $this->post("/cart/{$product->id}")
            ->assertRedirect('/login');
    }

    public function test_inactive_customer_cannot_login(): void
    {
        Customer::query()->create([
            'name' => 'Inactive Customer',
            'email' => 'inactive.customer@example.com',
            'password' => Hash::make('secret-password'),
            'is_active' => false,
        ]);

        $this->post('/login', [
            'email' => 'inactive.customer@example.com',
            'password' => 'secret-password',
        ])->assertSessionHasErrors('email');
    }

    private function customer(): Customer
    {
        return Customer::query()->create([
            'name' => 'Cart Customer',
            'email' => 'cart.customer@example.com',
            'password' => Hash::make('secret-password'),
            'is_active' => true,
        ]);
    }

    private function product(int $stock = 10): Product
    {
        $category = Category::query()->create([
            'name' => 'Cart Category',
            'slug' => 'cart-category',
            'is_active' => true,
        ]);

        return Product::query()->create([
            'category_id' => $category->id,
            'name' => 'Cart Product',
            'slug' => 'cart-product',
            'price' => 99,
            'stock' => $stock,
            'rating' => 4.5,
            'is_active' => true,
        ]);
    }
}
