<?php

namespace Tests\Feature;

use App\Models\User;
use App\Models\Product;
use App\Models\ShippingMethod;
use App\Services\CartManager;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Tests\TestCase;
use Livewire\Livewire;

class StorefrontShippingCalculationTest extends TestCase
{
    use RefreshDatabase;

    private User $admin;
    private $category;
    private Product $heavyProduct;
    private Product $lightProduct;

    protected function setUp(): void
    {
        parent::setUp();

        $this->admin = User::create([
            'name' => 'Admin User',
            'email' => 'admin@sawdabazar.com',
            'password' => bcrypt('password123'),
            'role' => 'admin',
        ]);

        $this->category = \App\Models\Category::create([
            'name' => 'General',
            'slug' => 'general',
            'is_visible' => true,
        ]);

        // 10 kg product (10000 grams) with is_weight_based = true
        $this->heavyProduct = Product::create([
            'name' => 'Heavy Dumbbell',
            'slug' => 'heavy-dumbbell',
            'sku' => 'HD-10KG',
            'price' => 1500.00,
            'compare_at_price' => 1800.00,
            'cost_price' => 1000.00,
            'quantity' => 10,
            'weight_grams' => 10000,
            'is_weight_based' => true, // Enabled weight-based shipping
            'published_at' => now(),
            'category_id' => $this->category->id,
        ]);

        // 500g product with is_weight_based = false (default)
        $this->lightProduct = Product::create([
            'name' => 'Light Dumbbell',
            'slug' => 'light-dumbbell',
            'sku' => 'LD-500G',
            'price' => 300.00,
            'compare_at_price' => 400.00,
            'cost_price' => 200.00,
            'quantity' => 20,
            'weight_grams' => 500,
            'is_weight_based' => false, // Flat rate shipping only
            'published_at' => now(),
            'category_id' => $this->category->id,
        ]);

        // Seed Bd locations
        \DB::table('bd_divisions')->insert(['id' => 1, 'name' => 'Dhaka', 'created_at' => now(), 'updated_at' => now()]);
        \DB::table('bd_districts')->insert(['id' => 1, 'division_id' => 1, 'name' => 'Dhaka', 'created_at' => now(), 'updated_at' => now()]);
        \DB::table('bd_upazilas')->insert(['id' => 1, 'district_id' => 1, 'name' => 'Mirpur', 'created_at' => now(), 'updated_at' => now()]);

        // Flat Rate Shipping
        ShippingMethod::create([
            'name' => 'Inside Dhaka Flat',
            'zone' => 'inside_dhaka',
            'pricing_type' => 'flat',
            'cost' => 80.00,
            'is_active' => true,
        ]);

        // Weight Based Shipping
        ShippingMethod::create([
            'name' => 'Weight Based Dhaka',
            'zone' => 'inside_dhaka',
            'pricing_type' => 'weight_based',
            'base_cost' => 50.00,
            'per_kg_rate' => 15.00,
            'is_active' => true,
        ]);
    }

    /**
     * Test shipping cost calculation for light and heavy items with flat vs weight-based methods.
     */
    public function test_storefront_checkout_calculates_correct_shipping_costs_for_weight_based_product(): void
    {
        // Add heavy product (is_weight_based = true) to cart
        CartManager::addToCart($this->heavyProduct->id, null, 1);

        Livewire::actingAs($this->admin);

        // When a weight-based product is in the cart, checkout should show only weight-based methods
        Livewire::test('storefront.checkout')
            ->set('selectedDivisionId', 1)
            ->set('selectedDistrictId', 1)
            ->set('selectedUpazilaId', 1)
            ->tap(function ($component) {
                // Should auto-select the weight-based method (since it is the only one returned for weight-based pricing)
                $this->assertEquals(200.00, $component->get('shippingCost')); // 50 base + (10 * 15) = 200
            });
    }

    /**
     * Test that if no product in cart is weight-based, only flat rate shipping methods are available.
     */
    public function test_storefront_checkout_uses_only_flat_rate_for_non_weight_based_product(): void
    {
        // Add light product (is_weight_based = false) to cart
        CartManager::addToCart($this->lightProduct->id, null, 2);

        Livewire::actingAs($this->admin);

        Livewire::test('storefront.checkout')
            ->set('selectedDivisionId', 1)
            ->set('selectedDistrictId', 1)
            ->set('selectedUpazilaId', 1)
            ->assertSet('shippingCost', 80.00) // Default flat rate inside Dhaka
            ->tap(function ($component) {
                $availableMethods = $component->instance()->getAvailableShippingMethods();
                $this->assertCount(1, $availableMethods);
                $this->assertEquals('Inside Dhaka Flat', $availableMethods->first()->name);
            });
    }

    /**
     * Test that if a weight-based product is in the cart but the zone (outside_dhaka) has no weight-based method,
     * the checkout falls back to the flat rate shipping method.
     */
    public function test_storefront_checkout_falls_back_to_flat_rate_when_no_weight_based_method_exists_in_zone(): void
    {
        // Seed an outside Dhaka district (district id 2)
        \DB::table('bd_divisions')->insert(['id' => 2, 'name' => 'Chittagong', 'created_at' => now(), 'updated_at' => now()]);
        \DB::table('bd_districts')->insert(['id' => 2, 'division_id' => 2, 'name' => 'Chittagong', 'created_at' => now(), 'updated_at' => now()]);
        \DB::table('bd_upazilas')->insert(['id' => 2, 'district_id' => 2, 'name' => 'Hathazari', 'created_at' => now(), 'updated_at' => now()]);

        // Flat Rate Shipping Outside Dhaka
        ShippingMethod::create([
            'name' => 'Outside Dhaka Flat',
            'zone' => 'outside_dhaka',
            'pricing_type' => 'flat',
            'cost' => 120.00,
            'is_active' => true,
        ]);

        // Add heavy product (is_weight_based = true) to cart
        CartManager::addToCart($this->heavyProduct->id, null, 1);

        Livewire::actingAs($this->admin);

        // When a weight-based product is in the cart, but selected district is outside Dhaka (Chittagong),
        // it should fall back to Outside Dhaka Flat (120.00) since there is no weight-based method for outside Dhaka.
        Livewire::test('storefront.checkout')
            ->set('selectedDivisionId', 2)
            ->set('selectedDistrictId', 2)
            ->set('selectedUpazilaId', 2)
            ->assertSet('shippingCost', 120.00)
            ->tap(function ($component) {
                $availableMethods = $component->instance()->getAvailableShippingMethods();
                $this->assertCount(1, $availableMethods);
                $this->assertEquals('Outside Dhaka Flat', $availableMethods->first()->name);
            });
    }
}
