<?php

namespace App\Filament\Pages;

use Carbon\Carbon;
use App\Models\Sale;
use App\Models\Cashbox;
use App\Models\Purchase;
use Filament\Pages\Page;
use App\Models\SaleReturn;
use Filament\Schemas\Schema;
use App\Models\CashMovement;
use App\Models\PurchaseReturn;
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 App\Exports\CashboxMovementExport;
use Maatwebsite\Excel\Facades\Excel;
use Mpdf\Mpdf;
use BezhanSalleh\FilamentShield\Traits\HasPageShield;
use Filament\Support\Icons\Heroicon;
use Illuminate\Support\Facades\Schema as SchemaFacade;

class CashboxMovementReport extends Page implements HasForms
{
    use InteractsWithForms;
    use HasPageShield;

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

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

    protected static string|\BackedEnum|null $navigationIcon = Heroicon::OutlinedBanknotes;

    protected static ?int $navigationSort = 5;

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

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

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

    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('cashbox_id')
                            ->label(__('filament/admin/reports.cashbox'))
                            ->placeholder(__('filament/admin/reports.select_cashbox'))
                            ->options(Cashbox::all()->mapWithKeys(fn($cashbox) => [$cashbox->id => $cashbox->name_ar ?? $cashbox->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),
                    ]),
            ]);
    }

    public function generateReport(): void
    {
        $cashbox_id = $this->data['cashbox_id'] ?? null;
        
        if (!$cashbox_id) {
            $this->report_data = [];
            return;
        }

        $cashbox = Cashbox::findOrFail($cashbox_id);
        $from_date = isset($this->data['from_date']) ? Carbon::parse($this->data['from_date'])->startOfDay() : null;
        $to_date = isset($this->data['to_date']) ? Carbon::parse($this->data['to_date'])->endOfDay() : Carbon::now()->endOfDay();

        // حساب الرصيد الافتتاحي (قبل تاريخ البداية)
        $opening_balance = $this->calculateOpeningBalance($cashbox, $from_date);

        // جلب جميع الحركات في الفترة المحددة
        $movements = $this->getMovements($cashbox, $from_date, $to_date);

        // حساب الرصيد الختامي والإجماليات
        $closing_balance = $opening_balance;
        $total_in = 0;
        $total_out = 0;
        
        $movements_with_balance = $movements->map(function ($movement) use (&$closing_balance, &$total_in, &$total_out) {
            $closing_balance += $movement['amount_change'];
            
            if ($movement['amount_change'] > 0) {
                $total_in += $movement['amount_change'];
            } else {
                $total_out += abs($movement['amount_change']);
            }
            
            return array_merge($movement, [
                'balance' => $closing_balance,
                'amount_in' => $movement['amount_change'] > 0 ? $movement['amount_change'] : 0,
                'amount_out' => $movement['amount_change'] < 0 ? abs($movement['amount_change']) : 0,
                'document_number' => $movement['reference_number'], // إضافة document_number للتصدير
            ]);
        });

        $this->report_data = [
            'cashbox' => $cashbox,
            'from_date' => $from_date?->format('Y-m-d'),
            'to_date' => $to_date->format('Y-m-d'),
            'opening_balance' => $opening_balance,
            'closing_balance' => $closing_balance,
            'total_in' => $total_in,
            'total_out' => $total_out,
            'movements' => $movements_with_balance,
        ];
    }

    /**
     * حساب الرصيد الافتتاحي قبل التاريخ المحدد
     */
    private function calculateOpeningBalance(Cashbox $cashbox, ?Carbon $from_date): float
    {
        // الرصيد الأساسي للخزينة
        $basic_balance = $cashbox->opening_balance;

        // جلب جميع الحركات قبل التاريخ
        $movements_query = CashMovement::where('cashbox_id', $cashbox->id);
        
        if ($from_date) {
            $movements_query->where('date', '<', $from_date);
        }

        $movements = $movements_query->get();

        $balance = $basic_balance;
        
        foreach ($movements as $movement) {
            if ($movement->movement_type === 'in') {
                $balance += $movement->amount;
            } else {
                $balance -= $movement->amount;
            }
        }

        return $balance;
    }

    /**
     * جلب جميع الحركات في الفترة المحددة
     */
    private function getMovements(Cashbox $cashbox, ?Carbon $from_date, Carbon $to_date): \Illuminate\Support\Collection
    {
        $movements = collect();

        // 1. حركات الخزينة المباشرة (CashMovement)
        $cashMovements = CashMovement::where('cashbox_id', $cashbox->id);
        
        if ($from_date) {
            $cashMovements->where('date', '>=', $from_date);
        }
        $cashMovements->where('date', '<=', $to_date);
        
        $cashMovements = $cashMovements->orderBy('date')->get();

        foreach ($cashMovements as $movement) {
            // تحديد النوع بناءً على reference_type أو movement_type
            $type = 'cash_in';
            $description = $movement->description;

            if ($movement->reference_type === 'Sale') {
                $type = 'sale';
                // استخدام وصف عربي موحد
                $description = 'مدفوع من فاتورة: ' . ($movement->reference_number ?? $movement->reference_id);
            } elseif ($movement->reference_type === 'Purchase') {
                $type = 'purchase';
                // استخدام وصف عربي موحد
                $description = 'مدفوع من فاتورة: ' . ($movement->reference_number ?? $movement->reference_id);
            } elseif ($movement->reference_type === 'SaleReturn') {
                $type = 'sale_return';
            } elseif ($movement->reference_type === 'PurchaseReturn') {
                $type = 'purchase_return';
            } elseif ($movement->movement_type === 'in') {
                $type = 'cash_in';
                if (!$description) {
                    $description = __('filament/admin/reports.cash_deposit');
                }
            } elseif ($movement->movement_type === 'out') {
                $type = 'cash_out';
                if (!$description) {
                    $description = __('filament/admin/reports.cash_withdrawal');
                }
            }

            $movements->push([
                'date' => $movement->date->format('Y-m-d H:i:s'),
                'type' => $type,
                'reference_number' => $movement->reference_number,
                'description' => $description,
                'reference_type' => $movement->reference_type ?? 'CashMovement',
                'reference_id' => $movement->reference_id,
                'amount' => $movement->amount,
                'amount_change' => $movement->movement_type === 'in' ? $movement->amount : -$movement->amount,
                'sort_date' => $movement->date,
            ]);
        }

        // جمع IDs للحركات المضافة من CashMovement لتجنب التكرار
        $addedSaleIds = $movements->where('reference_type', 'Sale')->pluck('reference_id')->toArray();
        $addedPurchaseIds = $movements->where('reference_type', 'Purchase')->pluck('reference_id')->toArray();

        // 2. المبيعات المدفوعة (للفواتير القديمة التي لم تُضاف في CashMovement)
        if (SchemaFacade::hasTable('sales')) {
            $sales = Sale::where('cashbox_id', $cashbox->id)
                ->where('status', 'confirmed')
                ->where('paid_amount', '>', 0)
                ->whereNotIn('id', $addedSaleIds);
            
            if ($from_date) {
                $sales->where('sale_date', '>=', $from_date);
            }
            $sales->where('sale_date', '<=', $to_date);
            
            foreach ($sales->with('customer')->get() as $sale) {
                $movements->push([
                    'date' => $sale->sale_date->format('Y-m-d H:i:s'),
                    'type' => 'sale',
                    'reference_number' => $sale->sale_number,
                    'description' => 'مدفوع من فاتورة: ' . $sale->sale_number,
                    'reference_type' => 'Sale',
                    'reference_id' => $sale->id,
                    'amount' => $sale->paid_amount,
                    'amount_change' => $sale->paid_amount,
                    'sort_date' => $sale->sale_date,
                ]);
            }
        }

        // 3. المشتريات المدفوعة (للفواتير القديمة التي لم تُضاف في CashMovement)
        if (SchemaFacade::hasTable('purchases')) {
            $purchases = Purchase::where('cashbox_id', $cashbox->id)
                ->where('status', 'confirmed')
                ->where('paid_amount', '>', 0)
                ->whereNotIn('id', $addedPurchaseIds);
            
            if ($from_date) {
                $purchases->where('purchase_date', '>=', $from_date);
            }
            $purchases->where('purchase_date', '<=', $to_date);
            
            foreach ($purchases->with('supplier')->get() as $purchase) {
                $movements->push([
                    'date' => $purchase->purchase_date->format('Y-m-d H:i:s'),
                    'type' => 'purchase',
                    'reference_number' => $purchase->purchase_number,
                    'description' => 'مدفوع من فاتورة: ' . $purchase->purchase_number,
                    'reference_type' => 'Purchase',
                    'reference_id' => $purchase->id,
                    'amount' => $purchase->paid_amount,
                    'amount_change' => -$purchase->paid_amount,
                    'sort_date' => $purchase->purchase_date,
                ]);
            }
        }

        // NOTE: Customer and Supplier payments removed as these resources were deleted
        // // 4. مدفوعات العملاء (إيرادات)
        // $customerPayments = CustomerPayment::where('cashbox_id', $cashbox->id)
        //     ->where('status', 'confirmed');
        // 
        // if ($from_date) {
        //     $customerPayments->where('created_at', '>=', $from_date);
        // }
        // $customerPayments->where('created_at', '<=', $to_date);

        // foreach ($customerPayments->with(['customer', 'supplier'])->get() as $payment) {
        //     $description = __('filament/admin/reports.customer_payment_received') . ' - ' . ($payment->customer->name ?? '');
        //     if ($payment->supplier) {
        //         $description .= ' (مرتبط بالمورد: ' . $payment->supplier->name . ')';
        //     }

        //     $movements->push([
        //         'date' => $payment->created_at->format('Y-m-d H:i:s'),
        //         'type' => 'customer_payment',
        //         'reference_number' => $payment->receipt_number,
        //         'description' => $description,
        //         'reference_type' => 'CustomerPayment',
        //         'reference_id' => $payment->id,
        //         'amount' => $payment->amount,
        //         'amount_change' => $payment->amount, // إيجابي
        //         'sort_date' => $payment->created_at,
        //     ]);
        // }

        // // 5. مدفوعات الموردين (مصروفات)
        // $supplierPayments = SupplierPayment::where('cashbox_id', $cashbox->id)
        //     ->where('status', 'confirmed');
        // 
        // if ($from_date) {
        //     $supplierPayments->where('created_at', '>=', $from_date);
        // }
        // $supplierPayments->where('created_at', '<=', $to_date);

        // foreach ($supplierPayments->with(['supplier', 'customer'])->get() as $payment) {
        //     $description = __('filament/admin/reports.supplier_payment_made') . ' - ' . ($payment->supplier->name ?? '');
        //     if ($payment->customer) {
        //         $description .= ' (مرتبط بالعميل: ' . $payment->customer->name . ')';
        //     }

        //     $movements->push([
        //         'date' => $payment->created_at->format('Y-m-d H:i:s'),
        //         'type' => 'supplier_payment',
        //         'reference_number' => $payment->disbursement_number,
        //         'description' => $description,
        //         'reference_type' => 'SupplierPayment',
        //         'reference_id' => $payment->id,
        //         'amount' => $payment->amount,
        //         'amount_change' => -$payment->amount, // سالب
        //         'sort_date' => $payment->created_at,
        //     ]);
        // }

        // 6. مرتجع عميل (مصروفات)
        $saleReturns = SaleReturn::where('cashbox_id', $cashbox->id)
            ->where('status', 'confirmed')
            ->where('refund_amount', '>', 0);
        
        if ($from_date) {
            $saleReturns->where('created_at', '>=', $from_date);
        }
        $saleReturns->where('created_at', '<=', $to_date);
        
        foreach ($saleReturns->get() as $return) {
            $movements->push([
                'date' => $return->created_at->format('Y-m-d H:i:s'),
                'type' => 'sale_return',
                'reference_number' => $return->return_number ?? $return->id,
                'description' => __('filament/admin/reports.sale_return_refund'),
                'reference_type' => 'SaleReturn',
                'reference_id' => $return->id,
                'amount' => $return->refund_amount,
                'amount_change' => -$return->refund_amount, // سالب
                'sort_date' => $return->created_at,
            ]);
        }

        // 7. مرتجع مورد (إيرادات)
        $purchaseReturns = PurchaseReturn::where('cashbox_id', $cashbox->id)
            ->where('status', 'confirmed')
            ->where('refund_amount', '>', 0);
        
        if ($from_date) {
            $purchaseReturns->where('created_at', '>=', $from_date);
        }
        $purchaseReturns->where('created_at', '<=', $to_date);
        
        foreach ($purchaseReturns->get() as $return) {
            $movements->push([
                'date' => $return->created_at->format('Y-m-d H:i:s'),
                'type' => 'purchase_return',
                'reference_number' => $return->return_number ?? $return->id,
                'description' => __('filament/admin/reports.purchase_return_refund'),
                'reference_type' => 'PurchaseReturn',
                'reference_id' => $return->id,
                'amount' => $return->refund_amount,
                'amount_change' => $return->refund_amount, // إيجابي
                'sort_date' => $return->created_at,
            ]);
        }

        // ترتيب الحركات حسب التاريخ
        return $movements->sortBy('sort_date')->values();
    }

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

        $cashbox = Cashbox::find($this->data['cashbox_id']);

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

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

        $cashbox = Cashbox::find($this->data['cashbox_id']);

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

        $mpdf->SetDirectionality('rtl');

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

        $mpdf->WriteHTML($html);

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

    public static function shouldRegisterNavigation(): bool
    {
        return true;
    }
}
