<?php

namespace Tests\Feature\Api;

use App\Models\Category;
use App\Models\Expense;
use App\Models\ExpenseCategory;
use App\Models\Ingredient;
use App\Models\Order;
use App\Models\Payment;
use App\Models\Product;
use App\Models\StockLedger;

class AnalyticsTest extends ApiTestCase
{
    protected function setUp(): void
    {
        parent::setUp();
        $this->createAuthenticatedUser();
        $this->seedTestData();
    }

    protected function seedTestData(): void
    {
        // Create categories and products
        $category = Category::create(['name' => 'Ice Cream', 'slug' => 'ice-cream', 'is_active' => true]);
        $product = Product::create([
            'name' => 'Vanilla Scoop',
            'slug' => 'vanilla-scoop',
            'category_id' => $category->id,
            'base_price' => 5.00,
            'is_active' => true,
        ]);

        // Create orders with payments
        $order = Order::create([
            'branch_id' => $this->branch->id,
            'user_id' => $this->user->id,
            'order_number' => 'ORD-A001',
            'status' => Order::STATUS_COMPLETED,
            'subtotal' => 50.00,
            'total_amount' => 50.00,
        ]);
        $order->items()->create([
            'product_id' => $product->id,
            'product_name' => $product->name,
            'quantity' => 10,
            'unit_price' => 5.00,
            'total_price' => 50.00,
        ]);
        Payment::create([
            'order_id' => $order->id,
            'user_id' => $this->user->id,
            'method' => 'cash',
            'amount' => 50.00,
            'status' => 'completed',
        ]);

        // Create expense category and expenses
        $expenseCategory = ExpenseCategory::create(['name' => 'Utilities', 'is_active' => true]);
        Expense::create([
            'branch_id' => $this->branch->id,
            'expense_category_id' => $expenseCategory->id,
            'user_id' => $this->user->id,
            'title' => 'Test Expense',
            'amount' => 20.00,
            'payment_method' => 'cash',
            'expense_date' => now(),
            'status' => 'approved',
        ]);

        // Create ingredients with stock
        $ingredient = Ingredient::create([
            'name' => 'Vanilla',
            'unit' => 'kg',
            'cost_per_unit' => 50.00,
            'reorder_level' => 20,
            'is_active' => true,
        ]);
        StockLedger::create([
            'branch_id' => $this->branch->id,
            'ingredient_id' => $ingredient->id,
            'quantity' => 10, // Below reorder level
        ]);
    }

    public function test_can_get_dashboard_summary(): void
    {
        $response = $this->getJson('/api/v1/analytics/dashboard');

        $this->assertSuccessResponse($response);
        $response->assertJsonStructure([
            'data' => [
                'date',
                'orders',
                'revenue',
                'expenses',
                'net_income',
            ],
        ]);
    }

    public function test_can_get_dashboard_summary_for_branch(): void
    {
        $response = $this->getJson("/api/v1/analytics/dashboard?branch_id={$this->branch->id}");

        $this->assertSuccessResponse($response);
    }

    public function test_can_get_sales_report(): void
    {
        $startDate = now()->subDays(30)->toDateString();
        $endDate = now()->toDateString();

        $response = $this->getJson("/api/v1/analytics/sales?start_date={$startDate}&end_date={$endDate}");

        $this->assertSuccessResponse($response);
        $response->assertJsonStructure([
            'data' => [
                'period',
                'summary',
                'daily_sales',
                'payment_methods',
            ],
        ]);
    }

    public function test_can_get_sales_report_for_branch(): void
    {
        $startDate = now()->subDays(30)->toDateString();
        $endDate = now()->toDateString();

        $response = $this->getJson("/api/v1/analytics/sales?start_date={$startDate}&end_date={$endDate}&branch_id={$this->branch->id}");

        $this->assertSuccessResponse($response);
    }

    public function test_can_get_expense_report(): void
    {
        $startDate = now()->subDays(30)->toDateString();
        $endDate = now()->toDateString();

        $response = $this->getJson("/api/v1/analytics/expenses?start_date={$startDate}&end_date={$endDate}");

        $this->assertSuccessResponse($response);
        $response->assertJsonStructure([
            'data' => [
                'period',
                'summary',
                'by_category',
                'daily_expenses',
            ],
        ]);
    }

    public function test_can_get_profit_loss_report(): void
    {
        $startDate = now()->subDays(30)->toDateString();
        $endDate = now()->toDateString();

        $response = $this->getJson("/api/v1/analytics/profit-loss?start_date={$startDate}&end_date={$endDate}");

        $this->assertSuccessResponse($response);
        $response->assertJsonStructure([
            'data' => [
                'period',
                'revenue',
                'expenses',
                'net_profit',
                'profit_margin',
            ],
        ]);
    }

    public function test_can_get_top_products(): void
    {
        $startDate = now()->subDays(30)->toDateString();
        $endDate = now()->toDateString();

        $response = $this->getJson("/api/v1/analytics/top-products?start_date={$startDate}&end_date={$endDate}&limit=10");

        $this->assertSuccessResponse($response);
    }

    public function test_can_get_hourly_sales(): void
    {
        $response = $this->getJson('/api/v1/analytics/hourly-sales');

        $this->assertSuccessResponse($response);
    }

    public function test_can_get_hourly_sales_for_specific_date(): void
    {
        $date = now()->toDateString();

        $response = $this->getJson("/api/v1/analytics/hourly-sales?date={$date}");

        $this->assertSuccessResponse($response);
    }

    public function test_can_get_sales_by_category(): void
    {
        $startDate = now()->subDays(30)->toDateString();
        $endDate = now()->toDateString();

        $response = $this->getJson("/api/v1/analytics/sales-by-category?start_date={$startDate}&end_date={$endDate}");

        $this->assertSuccessResponse($response);
    }

    public function test_can_get_sales_by_payment_method(): void
    {
        $startDate = now()->subDays(30)->toDateString();
        $endDate = now()->toDateString();

        $response = $this->getJson("/api/v1/analytics/sales-by-payment-method?start_date={$startDate}&end_date={$endDate}");

        $this->assertSuccessResponse($response);
    }

    public function test_can_get_branch_comparison(): void
    {
        // Create another branch with orders
        $branch2 = $this->createBranch(['name' => 'Branch 2', 'code' => 'BR002']);
        Order::create([
            'branch_id' => $branch2->id,
            'user_id' => $this->user->id,
            'order_number' => 'ORD-B001',
            'status' => Order::STATUS_COMPLETED,
            'subtotal' => 100.00,
            'total_amount' => 100.00,
        ]);

        $startDate = now()->subDays(30)->toDateString();
        $endDate = now()->toDateString();

        $response = $this->getJson("/api/v1/analytics/branch-comparison?start_date={$startDate}&end_date={$endDate}");

        $this->assertSuccessResponse($response);
    }

    public function test_can_get_inventory_valuation(): void
    {
        $response = $this->getJson('/api/v1/analytics/inventory-valuation');

        $this->assertSuccessResponse($response);
    }

    public function test_can_get_inventory_valuation_for_branch(): void
    {
        $response = $this->getJson("/api/v1/analytics/inventory-valuation?branch_id={$this->branch->id}");

        $this->assertSuccessResponse($response);
    }

    public function test_can_get_low_stock_alerts(): void
    {
        $response = $this->getJson('/api/v1/analytics/low-stock-alerts');

        $this->assertSuccessResponse($response);
    }

    public function test_can_get_low_stock_alerts_for_branch(): void
    {
        $response = $this->getJson("/api/v1/analytics/low-stock-alerts?branch_id={$this->branch->id}");

        $this->assertSuccessResponse($response);
    }

    public function test_dashboard_returns_correct_data_structure(): void
    {
        $response = $this->getJson('/api/v1/analytics/dashboard');

        $this->assertSuccessResponse($response);
        $data = $response->json('data');

        $this->assertArrayHasKey('orders', $data);
        $this->assertArrayHasKey('total', $data['orders']);
        $this->assertArrayHasKey('completed', $data['orders']);
        $this->assertArrayHasKey('pending', $data['orders']);
        $this->assertArrayHasKey('cancelled', $data['orders']);

        $this->assertArrayHasKey('revenue', $data);
        $this->assertArrayHasKey('total', $data['revenue']);
        $this->assertArrayHasKey('average_order_value', $data['revenue']);

        $this->assertArrayHasKey('expenses', $data);
        $this->assertArrayHasKey('total', $data['expenses']);
        $this->assertArrayHasKey('count', $data['expenses']);
    }

    public function test_profit_loss_calculates_correctly(): void
    {
        $startDate = now()->subDays(30)->toDateString();
        $endDate = now()->toDateString();

        $response = $this->getJson("/api/v1/analytics/profit-loss?start_date={$startDate}&end_date={$endDate}");

        $this->assertSuccessResponse($response);
        $data = $response->json('data');

        // Revenue should be 50 (from order), expenses 20 (from expense)
        // Net profit should be 30
        $this->assertGreaterThanOrEqual(0, $data['revenue']['net_sales']);
        $this->assertIsNumeric($data['net_profit']);
        $this->assertIsNumeric($data['profit_margin']);
    }
}
