<?php

namespace App\Filament\Pages;

use Carbon\Carbon;
use App\Models\Product;
use Filament\Pages\Page;
use App\Models\Warehouse;
use App\Models\ProductUnit;
use App\Models\OpeningBalance;
use Illuminate\Contracts\View\View;
use Filament\Forms\Components\Select;
use Filament\Forms\Contracts\HasForms;
use Filament\Schemas\Components\Section;
use Filament\Forms\Components\DatePicker;
use Filament\Forms\Concerns\InteractsWithForms;
use Filament\Schemas\Schema;
use App\Exports\AllItemsMovementExport;
use Maatwebsite\Excel\Facades\Excel;
use Mpdf\Mpdf;

class AllItemsMovementReport extends Page implements HasForms
{
    use InteractsWithForms;

    protected string $view = 'filament.pages.all-items-movement-report';

    public ?array $data = [];
    public ?array $report_data = null;

    protected static string|\UnitEnum|null $navigationGroup = 'products';

    protected static ?int $navigationSort = 9;

    public function getTitle(): string
    {
        return __('filament/admin/reports.all_items_movement');
    }

    public static function getNavigationLabel(): string
    {
        return __('filament/admin/reports.all_items_movement');
    }

    public static function getNavigationGroup(): ?string
    {
        return __('filament.navigation_groups.products');
    }

    public function mount(): void
    {
        $this->form->fill([
            'from_date' => now()->startOfMonth(),
            'to_date' => now()->endOfMonth(),
        ]);
    }

    public function form(Schema $schema): Schema
    {
        return $schema
            ->statePath('data')
            ->components([
                Section::make(__('filament/admin/reports.filters'))
                    ->columns(3)
                    ->schema([
                        Select::make('warehouse_id')
                            ->label(__('filament/admin/reports.warehouse'))
                            ->placeholder(__('filament/admin/reports.select_warehouse'))
                            ->options(Warehouse::all()->mapWithKeys(fn($warehouse) => [$warehouse->id => $warehouse->name_ar ?? $warehouse->name ?? 'مخزن']))
                            ->searchable()
                            ->required(),

                        DatePicker::make('from_date')
                            ->label(__('filament/admin/reports.from_date'))
                            ->native(false),

                        DatePicker::make('to_date')
                            ->label(__('filament/admin/reports.to_date'))
                            ->native(false)
                            ->default(now())
                            ->required(),
                    ]),
            ]);
    }

    public function generateReport(): void
    {
        $warehouse_id = $this->data['warehouse_id'] ?? null;

        if (!$warehouse_id) {
            $this->report_data = [];
            return;
        }

        $warehouse = Warehouse::findOrFail($warehouse_id);
        $from_date = isset($this->data['from_date']) ? Carbon::parse($this->data['from_date'])->startOfDay() : null;
        $to_date = Carbon::parse($this->data['to_date'])->endOfDay();

        // جلب جميع الأصناف
        $products = Product::with(['productUnits.unit', 'baseUnit'])->get();

        $items_data = [];
        $total_opening = 0;
        $total_purchases = 0;
        $total_customer_returns = 0;
        $total_sales = 0;
        $total_supplier_returns = 0;
        $total_closing = 0;

        foreach ($products as $product) {
            // حساب الرصيد الافتتاحي
            $opening_balance = $this->calculateOpeningBalance($product, $warehouse, $from_date);
            
            // حساب المشتريات في الفترة (بدون مرتجع العميل)
            $purchases = $this->calculatePurchasesOnly($product, $warehouse, $from_date, $to_date);
            
            // حساب مرتجع من العميل في الفترة
            $customer_returns = $this->calculateCustomerReturns($product, $warehouse, $from_date, $to_date);
            
            // حساب المبيعات في الفترة (بدون مرتجع المورد)
            $sales = $this->calculateSalesOnly($product, $warehouse, $from_date, $to_date);
            
            // حساب مرتجع للمورد في الفترة
            $supplier_returns = $this->calculateSupplierReturns($product, $warehouse, $from_date, $to_date);
            
            // حساب الرصيد الختامي
            $closing_balance = $opening_balance + $purchases + $customer_returns - $sales - $supplier_returns;

            $items_data[] = [
                'product' => $product,
                'opening_balance' => $opening_balance,
                'opening_balance_display' => $this->formatQuantityInUnits($opening_balance, $product),
                'purchases' => $purchases,
                'purchases_display' => $this->formatQuantityInUnits($purchases, $product),
                'customer_returns' => $customer_returns,
                'customer_returns_display' => $this->formatQuantityInUnits($customer_returns, $product),
                'sales' => $sales,
                'sales_display' => $this->formatQuantityInUnits($sales, $product),
                'supplier_returns' => $supplier_returns,
                'supplier_returns_display' => $this->formatQuantityInUnits($supplier_returns, $product),
                'closing_balance' => $closing_balance,
                'closing_balance_display' => $this->formatQuantityInUnits($closing_balance, $product),
            ];

            $total_opening += $opening_balance;
            $total_purchases += $purchases;
            $total_customer_returns += $customer_returns;
            $total_sales += $sales;
            $total_supplier_returns += $supplier_returns;
            $total_closing += $closing_balance;
            $total_sales += $sales;
            $total_closing += $closing_balance;
        }

        $this->report_data = [
            'warehouse' => $warehouse,
            'from_date' => $from_date?->format('Y-m-d'),
            'to_date' => $to_date->format('Y-m-d'),
            'items' => $items_data,
            'totals' => [
                'opening_balance' => $total_opening,
                'purchases' => $total_purchases,
                'customer_returns' => $total_customer_returns,
                'sales' => $total_sales,
                'supplier_returns' => $total_supplier_returns,
                'closing_balance' => $total_closing,
            ],
        ];
    }

    /**
     * حساب الرصيد الافتتاحي قبل التاريخ المحدد
     */
    private function calculateOpeningBalance(Product $product, Warehouse $warehouse, ?Carbon $from_date): float
    {
        // 1. الرصيد الافتتاحي الأساسي للصنف
        $basicOpeningBalance = OpeningBalance::where('product_id', $product->id)
            ->where('warehouse_id', $warehouse->id)
            ->sum('quantity') ?? 0;

        // دالة لتحويل الكمية إلى الوحدة الأساسية
        $convertToBase = function ($quantity, $unitId) use ($product) {
            if (!$unitId || $quantity == 0) {
                return 0;
            }
            
            $productUnit = $product->productUnits->firstWhere('unit_id', $unitId);
            if (!$productUnit) {
                return $quantity;
            }
            
            return $quantity * ($productUnit->conversion_factor ?? 1);
        };

        // 2. المشتريات قبل التاريخ
        $purchases = \App\Models\PurchaseItem::whereHas('purchase', function ($q) use ($warehouse, $from_date) {
            $q->where('warehouse_id', $warehouse->id);
            if ($from_date) {
                $q->where('created_at', '<', $from_date);
            }
        })->where('product_id', $product->id)->get();

        $purchasesTotal = 0;
        foreach ($purchases as $item) {
            $purchasesTotal += $convertToBase($item->quantity, $item->unit_id);
        }

        // 3. المبيعات قبل التاريخ
        $sales = \App\Models\SaleItem::whereHas('sale', function ($q) use ($warehouse, $from_date) {
            $q->where('warehouse_id', $warehouse->id);
            if ($from_date) {
                $q->where('created_at', '<', $from_date);
            }
        })->where('product_id', $product->id)->get();

        $salesTotal = 0;
        foreach ($sales as $item) {
            $salesTotal += $convertToBase($item->quantity, $item->unit_id);
        }

        // 4. مرتجع عميل قبل التاريخ (يضاف)
        $saleReturns = \App\Models\SaleReturnItem::whereHas('saleReturn', function ($q) use ($warehouse, $from_date) {
            $q->where('warehouse_id', $warehouse->id);
            if ($from_date) {
                $q->where('created_at', '<', $from_date);
            }
        })->where('product_id', $product->id)->get();

        $saleReturnsTotal = 0;
        foreach ($saleReturns as $item) {
            $saleReturnsTotal += $convertToBase($item->quantity, $item->unit_id);
        }

        // 5. مرتجع لمورد قبل التاريخ (يطرح)
        $purchaseReturns = \App\Models\PurchaseReturnItem::whereHas('purchaseReturn', function ($q) use ($warehouse, $from_date) {
            $q->where('warehouse_id', $warehouse->id);
            if ($from_date) {
                $q->where('created_at', '<', $from_date);
            }
        })->where('product_id', $product->id)->get();

        $purchaseReturnsTotal = 0;
        foreach ($purchaseReturns as $item) {
            $purchaseReturnsTotal += $convertToBase($item->quantity, $item->unit_id);
        }

        // الرصيد الافتتاحي = الرصيد الأساسي + المشتريات + مرتجع العملاء - المبيعات - مرتجع الموردين
        return $basicOpeningBalance + $purchasesTotal + $saleReturnsTotal - $salesTotal - $purchaseReturnsTotal;
    }

    /**
     * حساب إجمالي المشتريات فقط في الفترة (بدون مرتجع العميل)
     */
    private function calculatePurchasesOnly(Product $product, Warehouse $warehouse, ?Carbon $from_date, Carbon $to_date): float
    {
        $convertToBase = function ($quantity, $unitId) use ($product) {
            if (!$unitId || $quantity == 0) {
                return 0;
            }
            
            $productUnit = $product->productUnits->firstWhere('unit_id', $unitId);
            if (!$productUnit) {
                return $quantity;
            }
            
            return $quantity * ($productUnit->conversion_factor ?? 1);
        };

        // المشتريات فقط
        $purchases = \App\Models\PurchaseItem::whereHas('purchase', function ($q) use ($warehouse, $from_date, $to_date) {
            $q->where('warehouse_id', $warehouse->id);
            if ($from_date) {
                $q->where('created_at', '>=', $from_date);
            }
            $q->where('created_at', '<=', $to_date);
        })->where('product_id', $product->id)->get();

        $purchasesTotal = 0;
        foreach ($purchases as $item) {
            $purchasesTotal += $convertToBase($item->quantity, $item->unit_id);
        }

        return $purchasesTotal;
    }

    /**
     * حساب مرتجع من العميل في الفترة
     */
    private function calculateCustomerReturns(Product $product, Warehouse $warehouse, ?Carbon $from_date, Carbon $to_date): float
    {
        $convertToBase = function ($quantity, $unitId) use ($product) {
            if (!$unitId || $quantity == 0) {
                return 0;
            }
            
            $productUnit = $product->productUnits->firstWhere('unit_id', $unitId);
            if (!$productUnit) {
                return $quantity;
            }
            
            return $quantity * ($productUnit->conversion_factor ?? 1);
        };

        $saleReturns = \App\Models\SaleReturnItem::whereHas('saleReturn', function ($q) use ($warehouse, $from_date, $to_date) {
            $q->where('warehouse_id', $warehouse->id);
            if ($from_date) {
                $q->where('created_at', '>=', $from_date);
            }
            $q->where('created_at', '<=', $to_date);
        })->where('product_id', $product->id)->get();

        $saleReturnsTotal = 0;
        foreach ($saleReturns as $item) {
            $saleReturnsTotal += $convertToBase($item->quantity, $item->unit_id);
        }

        return $saleReturnsTotal;
    }

    /**
     * حساب إجمالي المبيعات فقط في الفترة (بدون مرتجع المورد)
     */
    private function calculateSalesOnly(Product $product, Warehouse $warehouse, ?Carbon $from_date, Carbon $to_date): float
    {
        $convertToBase = function ($quantity, $unitId) use ($product) {
            if (!$unitId || $quantity == 0) {
                return 0;
            }
            
            $productUnit = $product->productUnits->firstWhere('unit_id', $unitId);
            if (!$productUnit) {
                return $quantity;
            }
            
            return $quantity * ($productUnit->conversion_factor ?? 1);
        };

        // المبيعات فقط
        $sales = \App\Models\SaleItem::whereHas('sale', function ($q) use ($warehouse, $from_date, $to_date) {
            $q->where('warehouse_id', $warehouse->id);
            if ($from_date) {
                $q->where('created_at', '>=', $from_date);
            }
            $q->where('created_at', '<=', $to_date);
        })->where('product_id', $product->id)->get();

        $salesTotal = 0;
        foreach ($sales as $item) {
            $salesTotal += $convertToBase($item->quantity, $item->unit_id);
        }

        return $salesTotal;
    }

    /**
     * حساب مرتجع للمورد في الفترة
     */
    private function calculateSupplierReturns(Product $product, Warehouse $warehouse, ?Carbon $from_date, Carbon $to_date): float
    {
        $convertToBase = function ($quantity, $unitId) use ($product) {
            if (!$unitId || $quantity == 0) {
                return 0;
            }
            
            $productUnit = $product->productUnits->firstWhere('unit_id', $unitId);
            if (!$productUnit) {
                return $quantity;
            }
            
            return $quantity * ($productUnit->conversion_factor ?? 1);
        };

        $purchaseReturns = \App\Models\PurchaseReturnItem::whereHas('purchaseReturn', function ($q) use ($warehouse, $from_date, $to_date) {
            $q->where('warehouse_id', $warehouse->id);
            if ($from_date) {
                $q->where('created_at', '>=', $from_date);
            }
            $q->where('created_at', '<=', $to_date);
        })->where('product_id', $product->id)->get();

        $purchaseReturnsTotal = 0;
        foreach ($purchaseReturns as $item) {
            $purchaseReturnsTotal += $convertToBase($item->quantity, $item->unit_id);
        }

        return $purchaseReturnsTotal;
    }

    /**
     * حساب إجمالي المبيعات في الفترة
     */
    private function calculateSales(Product $product, Warehouse $warehouse, ?Carbon $from_date, Carbon $to_date): float
    {
        $convertToBase = function ($quantity, $unitId) use ($product) {
            if (!$unitId || $quantity == 0) {
                return 0;
            }
            
            $productUnit = $product->productUnits->firstWhere('unit_id', $unitId);
            if (!$productUnit) {
                return $quantity;
            }
            
            return $quantity * ($productUnit->conversion_factor ?? 1);
        };

        // المبيعات
        $sales = \App\Models\SaleItem::whereHas('sale', function ($q) use ($warehouse, $from_date, $to_date) {
            $q->where('warehouse_id', $warehouse->id);
            if ($from_date) {
                $q->where('created_at', '>=', $from_date);
            }
            $q->where('created_at', '<=', $to_date);
        })->where('product_id', $product->id)->get();

        $salesTotal = 0;
        foreach ($sales as $item) {
            $salesTotal += $convertToBase($item->quantity, $item->unit_id);
        }

        // مرتجع للمورد (يضاف)
        $purchaseReturns = \App\Models\PurchaseReturnItem::whereHas('purchaseReturn', function ($q) use ($warehouse, $from_date, $to_date) {
            $q->where('warehouse_id', $warehouse->id);
            if ($from_date) {
                $q->where('created_at', '>=', $from_date);
            }
            $q->where('created_at', '<=', $to_date);
        })->where('product_id', $product->id)->get();

        $purchaseReturnsTotal = 0;
        foreach ($purchaseReturns as $item) {
            $purchaseReturnsTotal += $convertToBase($item->quantity, $item->unit_id);
        }

        return $salesTotal + $purchaseReturnsTotal;
    }

    /**
     * تنسيق الكمية بالوحدة الكبرى والصغرى
     */
    private function formatQuantityInUnits(float $baseQuantity, Product $product): string
    {
        // إذا كان هناك وحدة أكبر محددة
        $largeUnit = $product->productUnits()
            ->where('is_default_purchase', false)
            ->whereHas('unit')
            ->orderBy('conversion_factor', 'desc')
            ->first();

        $smallUnit = $product->baseUnit;

        if (!$largeUnit || $largeUnit->conversion_factor <= 1) {
            // ليس لدينا وحدة أكبر، نعرض الوحدة الصغرى فقط
            return number_format($baseQuantity, 2) . ' ' . ($smallUnit?->name_ar ?? '');
        }

        $conversionFactor = $largeUnit->conversion_factor;
        $largeQuantity = floor($baseQuantity / $conversionFactor);
        $smallQuantity = $baseQuantity - ($largeQuantity * $conversionFactor);

        $result = '';
        if ($largeQuantity > 0) {
            $result .= number_format($largeQuantity, 0) . ' ' . ($largeUnit->unit->name_ar ?? '');
        }

        if ($smallQuantity > 0) {
            if ($result) {
                $result .= ' + ';
            }
            $result .= number_format($smallQuantity, 2) . ' ' . ($smallUnit?->name_ar ?? '');
        }

        return $result ?: '0';
    }

    public function exportExcel()
    {
        if (empty($this->report_data)) {
            $this->generateReport();
        }

        return Excel::download(
            new AllItemsMovementExport($this->report_data, $this->data['from_date'], $this->data['to_date']),
            'all-items-movement-' . now()->format('Y-m-d') . '.xlsx'
        );
    }

    public function exportPdf()
    {
        if (empty($this->report_data)) {
            $this->generateReport();
        }

        $mpdf = new Mpdf([
            'mode' => 'utf-8',
            'format' => 'A4',
            'orientation' => 'L',
            'default_font' => 'dejavusans',
            'autoScriptToLang' => true,
            'autoLangToFont' => true,
        ]);

        $mpdf->SetDirectionality('rtl');

        $html = view('reports.pdf.all-items-movement', [
            'data' => $this->report_data,
            'from_date' => $this->data['from_date'],
            'to_date' => $this->data['to_date'],
        ])->render();

        $mpdf->WriteHTML($html);

        return response()->streamDownload(function () use ($mpdf) {
            echo $mpdf->Output('', 'S');
        }, 'all-items-movement-' . now()->format('Y-m-d') . '.pdf');
    }
}
