<?php

namespace App\Filament\Pages;

use Carbon\Carbon;
use App\Models\Sale;
use App\Models\Purchase;
use Filament\Pages\Page;
use App\Models\SaleReturn;
use App\Models\CashMovement;
use Filament\Schemas\Schema;
use App\Models\PurchaseReturn;
use App\Models\CustomerPayment;
use App\Models\SupplierPayment;
use Illuminate\Contracts\View\View;
use Filament\Support\Icons\Heroicon;
use Filament\Forms\Contracts\HasForms;
use Filament\Schemas\Components\Section;
use Filament\Forms\Components\DatePicker;
use Filament\Forms\Concerns\InteractsWithForms;
use App\Exports\ProfitExport;
use Maatwebsite\Excel\Facades\Excel;
use Mpdf\Mpdf;
use BezhanSalleh\FilamentShield\Traits\HasPageShield;

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

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

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

    protected static ?int $navigationSort = 7;

    public ?array $data = [];

    public ?array $report_data = null;

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

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

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

    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()
                    ->columns(2)
                    ->schema([
                        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
    {
        $formData = $this->form->getState();
        $from_date = !empty($formData['from_date']) ? Carbon::parse($formData['from_date'])->startOfDay() : null;
        $to_date = !empty($formData['to_date']) ? Carbon::parse($formData['to_date'])->endOfDay() : Carbon::now()->endOfDay();

        if ($from_date && $to_date->lt($from_date)) {
            \Filament\Notifications\Notification::make()
                ->title('تاريخ النهاية يجب أن يكون بعد أو يساوي تاريخ البداية')
                ->warning()
                ->send();
            $this->report_data = [];
            return;
        }

        // ========== INCOME CALCULATIONS ==========
        
        // 1. Customer Payments
        $customer_payments_query = CustomerPayment::where('status', 'confirmed');
        if ($from_date) {
            $customer_payments_query->where('created_at', '>=', $from_date);
        }
        $customer_payments_query->where('created_at', '<=', $to_date);
        $customer_payments = $customer_payments_query->sum('amount');

        // 2. Sale Payments
        $sale_payments_query = Sale::query();
        if ($from_date) {
            $sale_payments_query->where('created_at', '>=', $from_date);
        }
        $sale_payments_query->where('created_at', '<=', $to_date);
        $sale_payments = $sale_payments_query->sum('paid_amount');

        // 3. Sale Return Refunds (deduct)
        $sale_return_refunds_query = SaleReturn::query();
        if ($from_date) {
            $sale_return_refunds_query->where('created_at', '>=', $from_date);
        }
        $sale_return_refunds_query->where('created_at', '<=', $to_date);
        $sale_return_refunds = $sale_return_refunds_query->sum('paid_amount');

        // 4. Cash In
        $cash_in_query = CashMovement::where('movement_type', 'in');
        if ($from_date) {
            $cash_in_query->where('date', '>=', $from_date);
        }
        $cash_in_query->where('date', '<=', $to_date);
        $cash_in = $cash_in_query->sum('amount');

        $total_income = $customer_payments + $sale_payments + $cash_in - $sale_return_refunds;

        // ========== EXPENSE CALCULATIONS ==========
        
        // 1. Supplier Payments
        $supplier_payments_query = SupplierPayment::where('status', 'confirmed');
        if ($from_date) {
            $supplier_payments_query->where('created_at', '>=', $from_date);
        }
        $supplier_payments_query->where('created_at', '<=', $to_date);
        $supplier_payments = $supplier_payments_query->sum('amount');

        // 2. Purchase Payments
        $purchase_payments_query = Purchase::query();
        if ($from_date) {
            $purchase_payments_query->where('created_at', '>=', $from_date);
        }
        $purchase_payments_query->where('created_at', '<=', $to_date);
        $purchase_payments = $purchase_payments_query->sum('paid_amount');

        // 3. Purchase Return Refunds (deduct from expenses)
        $purchase_return_refunds_query = PurchaseReturn::query();
        if ($from_date) {
            $purchase_return_refunds_query->where('created_at', '>=', $from_date);
        }
        $purchase_return_refunds_query->where('created_at', '<=', $to_date);
        $purchase_return_refunds = $purchase_return_refunds_query->sum('paid_amount');

        // 4. Cash Out
        $cash_out_query = CashMovement::where('movement_type', 'out');
        if ($from_date) {
            $cash_out_query->where('date', '>=', $from_date);
        }
        $cash_out_query->where('date', '<=', $to_date);
        $cash_out = $cash_out_query->sum('amount');

        $total_expenses = $supplier_payments + $purchase_payments + $cash_out - $purchase_return_refunds;

        // ========== SALES PROFIT CALCULATIONS ==========
        
        // Get all sales in period and calculate profit based on item-level cost
        $sales_profit_query = Sale::query()
            ->with(['items.product.productUnits']);
        if ($from_date) {
            $sales_profit_query->where('created_at', '>=', $from_date);
        }
        $sales_profit_query->where('created_at', '<=', $to_date);
        $sales = $sales_profit_query->get();

        $total_sale_value = 0;
        $total_sale_cost = 0;

        foreach ($sales as $sale) {
            foreach ($sale->items as $item) {
                // Get base unit info - compare with product's base_unit_id
                $baseUnit = $item->product->productUnits()
                    ->where('unit_id', $item->product->base_unit_id)
                    ->first();

                if ($baseUnit) {
                    // Convert quantity to base unit
                    $currentUnit = $item->product->productUnits()
                        ->where('unit_id', $item->unit_id)
                        ->first();
                    
                    $conversion_factor = $currentUnit ? $currentUnit->conversion_factor : 1;
                    $quantity_in_base = $item->quantity * $conversion_factor;

                    // Calculate sale value and cost
                    $sale_price = $baseUnit->selling_price ?? 0;
                    $purchase_price = $baseUnit->purchase_price ?? 0;

                    $total_sale_value += $quantity_in_base * $sale_price;
                    $total_sale_cost += $quantity_in_base * $purchase_price;
                }
            }
        }

        $gross_sales_profit = $total_sale_value - $total_sale_cost;

        // Deduct sale returns from sales profit
        $sale_returns_query = SaleReturn::query()
            ->with(['items.product.productUnits']);
        if ($from_date) {
            $sale_returns_query->where('created_at', '>=', $from_date);
        }
        $sale_returns_query->where('created_at', '<=', $to_date);
        $sale_returns = $sale_returns_query->get();

        $total_return_value = 0;
        $total_return_cost = 0;

        foreach ($sale_returns as $return) {
            foreach ($return->items as $item) {
                $baseUnit = $item->product->productUnits()
                    ->where('unit_id', $item->product->base_unit_id)
                    ->first();

                if ($baseUnit) {
                    $currentUnit = $item->product->productUnits()
                        ->where('unit_id', $item->unit_id)
                        ->first();
                    
                    $conversion_factor = $currentUnit ? $currentUnit->conversion_factor : 1;
                    $quantity_in_base = $item->quantity * $conversion_factor;

                    $sale_price = $baseUnit->selling_price ?? 0;
                    $purchase_price = $baseUnit->purchase_price ?? 0;

                    $total_return_value += $quantity_in_base * $sale_price;
                    $total_return_cost += $quantity_in_base * $purchase_price;
                }
            }
        }

        $net_sales_profit = $gross_sales_profit - ($total_return_value - $total_return_cost);

        // ========== FINAL CALCULATIONS ==========
        
        $net_profit = $total_income - $total_expenses;
        $profit_margin = $total_income > 0 ? ($net_profit / $total_income) * 100 : 0;

        $this->report_data = [
            'from_date' => $from_date?->format('Y-m-d'),
            'to_date' => $to_date->format('Y-m-d'),
            'income' => [
                'customer_payments' => $customer_payments,
                'sale_payments' => $sale_payments,
                'cash_in' => $cash_in,
                'sale_return_refunds' => $sale_return_refunds,
                'total' => $total_income,
            ],
            'expenses' => [
                'supplier_payments' => $supplier_payments,
                'purchase_payments' => $purchase_payments,
                'cash_out' => $cash_out,
                'purchase_return_refunds' => $purchase_return_refunds,
                'total' => $total_expenses,
            ],
            'sales_analysis' => [
                'total_sale_value' => $total_sale_value,
                'total_sale_cost' => $total_sale_cost,
                'gross_sales_profit' => $gross_sales_profit,
                'total_return_value' => $total_return_value,
                'total_return_cost' => $total_return_cost,
                'net_sales_profit' => $net_sales_profit,
            ],
            'summary' => [
                'net_profit' => $net_profit,
                'profit_margin' => $profit_margin,
            ],
        ];
    }

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

        return Excel::download(
            new ProfitExport($this->report_data, $this->data['from_date'], $this->data['to_date']),
            'profit-report-' . 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.profit', [
            'data' => $this->report_data,
        ])->render();

        $mpdf->WriteHTML($html);

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