<?php

namespace Tests\Unit;

use App\Models\Product;
use App\Models\Order;
use App\Models\OrderItem;
use App\Services\ProfitService;
use Tests\TestCase;
use Illuminate\Foundation\Testing\RefreshDatabase;

class ProfitCalculationTest extends TestCase
{
    use RefreshDatabase;

    public function test_unit_profit_calculation()
    {
        // Create a product with purchase price
        $product = Product::factory()->create([
            'price' => 100.00,
            'purchase_price' => 50.00,
        ]);

        // Create an order item
        $orderItem = OrderItem::create([
            'order_id' => 1,
            'product_id' => $product->id,
            'name' => $product->name,
            'sku' => 'TEST-SKU',
            'qty' => 2,
            'price' => 100.00,
            'line_total' => 200.00,
            'purchase_price' => 50.00,
            'allocated_discount' => 20.00,
            'allocated_shipping' => 10.00,
            'allocated_extra_costs' => 0.00,
        ]);

        // Test unit profit calculation
        // UnitProfit = (unit_sale_price - unit_discount_allocation) - purchase_price - unit_allocated_shipping - unit_allocated_extra_costs
        // UnitProfit = (100 - 10) - 50 - 5 - 0 = 35
        $expectedUnitProfit = 35.00;
        $this->assertEquals($expectedUnitProfit, $orderItem->unit_profit);

        // Test total profit calculation
        $expectedTotalProfit = $expectedUnitProfit * 2; // 70.00
        $this->assertEquals($expectedTotalProfit, $orderItem->total_profit);

        // Test revenue calculation
        $expectedRevenue = (100 * 2) - 20; // 180.00
        $this->assertEquals($expectedRevenue, $orderItem->revenue);

        // Test profit margin calculation
        $expectedMargin = ($expectedTotalProfit / $expectedRevenue) * 100; // 38.89%
        $this->assertEquals(round($expectedMargin, 2), $orderItem->profit_margin);
    }

    public function test_product_profit_methods()
    {
        // Test product with purchase price
        $product = Product::factory()->create([
            'price' => 75.00,
            'purchase_price' => 45.00,
        ]);

        $this->assertTrue($product->hasPurchasePrice());
        $this->assertEquals(30.00, $product->unit_profit);
        $this->assertEquals(40.00, $product->profit_margin); // (30/75)*100

        // Test product without purchase price
        $productNoPurchase = Product::factory()->create([
            'price' => 75.00,
            'purchase_price' => null,
        ]);

        $this->assertFalse($productNoPurchase->hasPurchasePrice());
        $this->assertNull($productNoPurchase->unit_profit);
        $this->assertNull($productNoPurchase->profit_margin);
    }

    public function test_profit_service_calculations()
    {
        $profitService = new ProfitService();

        // Create test order items
        $orderItems = collect([
            (object) [
                'revenue' => 100.00,
                'total_cogs' => 60.00,
                'total_profit' => 40.00,
                'purchase_price' => 30.00,
            ],
            (object) [
                'revenue' => 200.00,
                'total_cogs' => 120.00,
                'total_profit' => 80.00,
                'purchase_price' => 60.00,
            ],
        ]);

        // Mock the hasProfitData method
        foreach ($orderItems as $item) {
            $item->hasProfitData = function() { return true; };
        }

        $metrics = $profitService->calculateProfitMetrics($orderItems);

        $this->assertEquals(300.00, $metrics['total_revenue']);
        $this->assertEquals(180.00, $metrics['total_cogs']);
        $this->assertEquals(120.00, $metrics['total_profit']);
        $this->assertEquals(40.00, $metrics['profit_margin_percent']); // (120/300)*100
        $this->assertEquals(2, $metrics['items_with_profit_data']);
        $this->assertEquals(100.00, $metrics['profit_data_coverage_percent']);
    }

    public function test_sample_calculation_from_requirements()
    {
        // Test case from requirements: product with purchase 50, sale 75, no discounts → unit profit 25
        $orderItem = OrderItem::create([
            'order_id' => 1,
            'product_id' => 1,
            'name' => 'Test Product',
            'sku' => 'TEST-SKU',
            'qty' => 1,
            'price' => 75.00,
            'line_total' => 75.00,
            'purchase_price' => 50.00,
            'allocated_discount' => 0.00,
            'allocated_shipping' => 0.00,
            'allocated_extra_costs' => 0.00,
        ]);

        // UnitProfit = (75 - 0) - 50 - 0 - 0 = 25
        $this->assertEquals(25.00, $orderItem->unit_profit);
        $this->assertEquals(25.00, $orderItem->total_profit);
    }

    public function test_discount_allocation_calculation()
    {
        // Test case: Single product: purchase 40, sale 100, discount 10 → allocated discount 10 → profit = (100 - 10) - 40 = 50
        $orderItem = OrderItem::create([
            'order_id' => 1,
            'product_id' => 1,
            'name' => 'Test Product',
            'sku' => 'TEST-SKU',
            'qty' => 1,
            'price' => 100.00,
            'line_total' => 100.00,
            'purchase_price' => 40.00,
            'allocated_discount' => 10.00,
            'allocated_shipping' => 0.00,
            'allocated_extra_costs' => 0.00,
        ]);

        // UnitProfit = (100 - 10) - 40 - 0 - 0 = 50
        $this->assertEquals(50.00, $orderItem->unit_profit);
        $this->assertEquals(50.00, $orderItem->total_profit);
    }
}