<?php

namespace App\Services;

use App\Models\DailyProductSummary;
use App\Models\DailySalesSummary;
use App\Models\Expense;
use App\Models\Order;
use App\Models\SaleReturn;
use Illuminate\Support\Facades\DB;

class DailySummaryService
{
    public function rebuildForDate(string $date, ?int $companyId = null, ?int $branchId = null): void
    {
        $orders = Order::query()
            ->with(['items', 'payments.paymentMethod', 'customer'])
            ->whereDate('created_at', $date)
            ->when($companyId !== null, fn ($query) => $query->where('company_id', $companyId))
            ->when($branchId !== null, fn ($query) => $query->where('branch_id', $branchId))
            ->whereIn('status', ['completed', 'processing', 'refunded', 'partially_refunded'])
            ->get()
            ->groupBy(fn (Order $order) => "{$order->company_id}:{$order->branch_id}");

        $returns = SaleReturn::query()
            ->with('items')
            ->whereDate('created_at', $date)
            ->when($companyId !== null, fn ($query) => $query->where('company_id', $companyId))
            ->when($branchId !== null, fn ($query) => $query->where('branch_id', $branchId))
            ->get()
            ->groupBy(fn (SaleReturn $saleReturn) => "{$saleReturn->company_id}:{$saleReturn->branch_id}");

        $expenses = Expense::query()
            ->whereDate('expense_date', $date)
            ->where('is_approved', true)
            ->when($companyId !== null, fn ($query) => $query->where('company_id', $companyId))
            ->when($branchId !== null, fn ($query) => $query->where('branch_id', $branchId))
            ->get()
            ->groupBy(fn (Expense $expense) => "{$expense->company_id}:{$expense->branch_id}");

        $keys = collect($orders->keys())
            ->merge($returns->keys())
            ->merge($expenses->keys())
            ->unique()
            ->values();

        foreach ($keys as $key) {
            [$resolvedCompanyId, $resolvedBranchId] = array_map('intval', explode(':', $key));
            /** @var \Illuminate\Support\Collection<int, Order> $group */
            $group = $orders->get($key, collect());

            $summary = [
                'total_orders' => $group->count(),
                'total_items_sold' => 0,
                'gross_sales' => 0,
                'total_discounts' => 0,
                'total_taxes' => 0,
                'net_sales' => 0,
                'total_cost' => 0,
                'gross_profit' => 0,
                'total_returns' => 0,
                'cash_payments' => 0,
                'mpesa_payments' => 0,
                'card_payments' => 0,
                'other_payments' => 0,
                'total_expenses' => 0,
                'new_customers' => 0,
            ];

            $productRows = [];
            $customerIds = [];

            foreach ($group as $order) {
                $summary['gross_sales'] += (float) $order->subtotal;
                $summary['total_discounts'] += (float) $order->discount_amount;
                $summary['total_taxes'] += (float) $order->tax_amount;
                $summary['net_sales'] += (float) $order->total_amount;

                if ($order->customer_id !== null) {
                    $customerIds[] = $order->customer_id;
                }

                foreach ($order->items as $item) {
                    $summary['total_items_sold'] += (float) $item->quantity;
                    $summary['total_cost'] += (float) $item->cost_price * (float) $item->quantity;

                    $productKey = "{$resolvedBranchId}:{$item->product_id}";
                    $productRows[$productKey] ??= [
                        'company_id' => $resolvedCompanyId,
                        'branch_id' => $resolvedBranchId,
                        'product_id' => $item->product_id,
                        'summary_date' => $date,
                        'quantity_sold' => 0,
                        'quantity_returned' => 0,
                        'gross_revenue' => 0,
                        'total_cost' => 0,
                        'gross_profit' => 0,
                    ];

                    $productRows[$productKey]['quantity_sold'] += (float) $item->quantity;
                    $productRows[$productKey]['gross_revenue'] += (float) $item->total_amount;
                    $productRows[$productKey]['total_cost'] += (float) $item->cost_price * (float) $item->quantity;
                }

                foreach ($order->payments as $payment) {
                    $bucket = match ($payment->paymentMethod?->type) {
                        'cash' => 'cash_payments',
                        'mpesa' => 'mpesa_payments',
                        'card' => 'card_payments',
                        default => 'other_payments',
                    };

                    $summary[$bucket] += (float) $payment->amount;
                }
            }

            $summary['gross_profit'] = $summary['net_sales'] - $summary['total_cost'];
            $summary['new_customers'] = count(array_unique($customerIds));

            foreach ($returns->get($key, collect()) as $saleReturn) {
                $summary['total_returns'] += (float) $saleReturn->total_refund_amount;

                foreach ($saleReturn->items as $returnItem) {
                    $productKey = "{$resolvedBranchId}:{$returnItem->product_id}";

                    if (! isset($productRows[$productKey])) {
                        $productRows[$productKey] = [
                            'company_id' => $resolvedCompanyId,
                            'branch_id' => $resolvedBranchId,
                            'product_id' => $returnItem->product_id,
                            'summary_date' => $date,
                            'quantity_sold' => 0,
                            'quantity_returned' => 0,
                            'gross_revenue' => 0,
                            'total_cost' => 0,
                            'gross_profit' => 0,
                        ];
                    }

                    $productRows[$productKey]['quantity_returned'] += (float) $returnItem->quantity;
                }
            }

            $summary['total_expenses'] = (float) $expenses->get($key, collect())->sum('amount');

            DailySalesSummary::updateOrCreate(
                [
                    'branch_id' => $resolvedBranchId,
                    'summary_date' => $date,
                ],
                [
                    'company_id' => $resolvedCompanyId,
                    ...$summary,
                ]
            );

            foreach ($productRows as $row) {
                $row['gross_profit'] = $row['gross_revenue'] - $row['total_cost'];

                DailyProductSummary::updateOrCreate(
                    [
                        'branch_id' => $row['branch_id'],
                        'product_id' => $row['product_id'],
                        'summary_date' => $row['summary_date'],
                    ],
                    $row
                );
            }
        }
    }
}
