<?php

namespace App\Filament\Reports;

use App\Models\Customer;
use App\Models\MonyImport;
use App\Models\MonyExport;
use App\Models\Sale;
use App\Models\Purchase;
use EightyNine\Reports\Components\Text;
use EightyNine\Reports\Report;
use EightyNine\Reports\Components\Body;
use EightyNine\Reports\Components\Footer;
use EightyNine\Reports\Components\Header;
use Filament\Forms\Form;
use Filament\Forms\Components\DatePicker;
use Filament\Forms\Components\Select;
use Illuminate\Support\Carbon;

class CustomerReport extends Report
{
    protected static ?string $navigationIcon = 'heroicon-o-user';

    public static function getNavigationLabel(): string
    {
        return "تقرير العملاء";
    }

    public function getTitle(): string
    {
        return "تقرير العملاء";
    }

    protected static ?int $navigationSort = 6;

    protected static ?string $navigationGroup = 'التقارير';

    public function header(Header $header): Header
    {
        return $header
            ->schema([
                Header\Layout\HeaderRow::make()
                    ->schema([
                        Text::make("حركة العملاء")
                            ->fontXl()
                            ->fontBold()
                            ->primary(),
                        Text::make("هذا التقرير يعرض تفاصيل معاملات العملاء بين التاريخين المحددين.")
                            ->fontSm()
                            ->secondary(),
                    ])
                    ->alignBottom(),
            ]);
    }

    function getCarbonInstancesFromDateString(?string $dateString): array
    {
        if (!$dateString) {
            return [null, null];
        }

        $dates = explode(" - ", $dateString);

        [$from, $to] = $dates;

        $from = Carbon::createFromFormat("d/m/Y", $from);
        $to = Carbon::createFromFormat("d/m/Y", $to);

        return [$from, $to];
    }

    public function body(Body $body): Body
    {
        return $body
            ->schema([
                Body\Layout\BodyColumn::make()
                    ->schema([
                        Body\Table::make()
                            ->columns([
                                Body\TextColumn::make("date")->date('D-d-M-Y')->label("التاريخ"),
                                Body\TextColumn::make("type")->label("نوع المعاملة"),
                                Body\TextColumn::make("products")->label("المنتجات"),
                                Body\TextColumn::make("amount")->label("القيمة"),
                                Body\TextColumn::make("balance")->label("الرصيد"),
                                Body\TextColumn::make("notes")->label("الملاحظات"),
                            ])
                            ->data(
                                function (?array $filters) {
                                    if (empty($filters['date']) && !empty($filters['from_date']) && !empty($filters['to_date'])) {
                                        $filters['date'] = Carbon::parse($filters['from_date'])->format('d/m/Y') . ' - ' . Carbon::parse($filters['to_date'])->format('d/m/Y');
                                    }

                                    // Validate customer_id and date filters
                                    if (!isset($filters['customer_id']) || !is_string($filters['customer_id'])) {
                                        return collect([]); // Ensure customer_id is valid
                                    }

                                    $customerId = $filters['customer_id'];

                                    if (!isset($filters['date']) || !is_string($filters['date'])) {
                                        return collect([]); // Ensure date filter is valid
                                    }

                                    [$from, $to] = $this->getCarbonInstancesFromDateString($filters['date']);

                                    if (!$from || !$to) {
                                        return collect([]); // Ensure date range is valid
                                    }

                                    // Calculate initial balance
                                    $initialBalance = Customer::find($customerId)->first_mony ?? 0;

                                    // Add pre-date range transactions
                                    // Calculate sum for sales
                                    $sales = Sale::where('customer_id', $customerId)
                                        ->where('date', '<', $from)
                                        ->with('products')
                                        ->get();

                                    $salesTotal = $sales->reduce(function ($carry, $sale) {
                                        return $carry + $sale->products->sum('pivot.total');
                                    }, 0);

                                    $initialBalance += $salesTotal;

                                    // Calculate sum for purchases
                                    $purchases = Purchase::where('customer_id', $customerId)
                                        ->where('date', '<', $from)
                                        ->with('products')
                                        ->get();

                                    $purchasesTotal = $purchases->reduce(function ($carry, $purchase) {
                                        return $carry + $purchase->products->sum('pivot.total');
                                    }, 0);

                                    $initialBalance -= $purchasesTotal;

                                    // الواردات النقدية: عندما يدفع العميل نقداً للعميل
                                    $initialBalance -= MonyImport::where('customer_id', $customerId)
                                        ->where('date', '<', $from)
                                        ->sum('value');

                                    // الصادرات النقدية: عندما نعطي العميل نقداً
                                    $initialBalance += MonyExport::where('customer_id', $customerId)
                                        ->where('date', '<', $from)
                                        ->sum('value');

                                    // Fetch transactions within the date range
                                    $sales = Sale::with('products', 'customer')
                                        ->where('customer_id', $customerId)
                                        ->whereBetween('date', [$from, $to])
                                        ->get();

                                    $purchases = Purchase::with('products', 'customer')
                                        ->where('customer_id', $customerId)
                                        ->whereBetween('date', [$from, $to])
                                        ->get();

                                    $monyImports = MonyImport::where('customer_id', $customerId)
                                        ->whereBetween('date', [$from, $to])
                                        ->get();

                                    $monyExports = MonyExport::where('customer_id', $customerId)
                                        ->whereBetween('date', [$from, $to])
                                        ->get();

                                    // Merge transactions
                                    $transactions = collect([[
                                        'date' => $from->subDay()->format('Y-m-d'),
                                        'type' => 'رصيد أول',
                                        'products' => 'N/A',
                                        'amount' => $initialBalance,
                                        'notes' => 'رصيد أول',
                                    ]])->merge(
                                        $sales->map(fn($sale) => [
                                            'date' => $sale->date,
                                            'type' => 'بيع',
                                            'products' => $sale->products->pluck('name')->implode(', '),
                                            'amount' => $sale->products->sum('pivot.total'),
                                            'notes' => $sale->notes ?? '',
                                        ])
                                    )->merge(
                                        $purchases->map(fn($purchase) => [
                                            'date' => $purchase->date,
                                            'type' => 'شراء',
                                            'products' => $purchase->products->pluck('name')->implode(', '),
                                            'amount' => -$purchase->products->sum('pivot.total'),
                                            'notes' => $purchase->notes ?? '',
                                        ])
                                    )->merge(
                                        $monyImports->map(fn($import) => [
                                            'date' => $import->date,
                                            'type' => 'وارد نقدي',
                                            'products' => 'N/A',
                                            'amount' => -$import->value,
                                            'notes' => $import->notes ?? '',
                                        ])
                                    )->merge(
                                        $monyExports->map(fn($export) => [
                                            'date' => $export->date,
                                            'type' => 'صرف نقدي',
                                            'products' => 'N/A',
                                            'amount' => $export->value,
                                            'notes' => $export->notes ?? '',
                                        ])
                                    )->sortBy('date');

                                    // Calculate running balance
                                    $balance = 0;
                                    return $transactions->map(function ($transaction) use (&$balance) {
                                        $balance += $transaction['amount'];
                                        return array_merge($transaction, ['balance' => $balance]);
                                    });
                                }
                            ),
                    ]),
            ]);
    }

    public function footer(Footer $footer): Footer
    {
        return $footer
            ->schema([
                Text::make("تاريخ التقرير: " . now()->format("d/m/Y H:i:s"))
                    ->subtitle(),
            ]);
    }

    public function filterForm(Form $form): Form
    {
        return $form
            ->schema([
                DatePicker::make('from_date')
                    ->label('من تاريخ')
                    ->native(false)
                    ->required(),

                DatePicker::make('to_date')
                    ->label('إلى تاريخ')
                    ->native(false)
                    ->required(),

                Select::make('customer_id')
                    ->label('العملاء')
                    ->options(
                        Customer::all()->pluck('name', 'id')->toArray()
                    )
                    ->placeholder('حدد العميل')
                    ->preload()
                    ->required(), // Customer is required
            ]);
    }
}