<?php

namespace App\Filament\Reports;

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

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

    public static function getNavigationLabel(): string
    {
        return 'تقرير المنتج';
    }

    public function getTitle(): string
    {
        return 'تقرير المنتج';
    }

    protected static ?int $navigationSort = 10;

    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(),
            ]);
    }

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

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

        if (count($dates) !== 2) {
            return [null, null];
        }

        try {
            $from = Carbon::createFromFormat('d/m/Y', $dates[0]);
            $to = Carbon::createFromFormat('d/m/Y', $dates[1]);
        } catch (\Exception $e) {
            return [null, null];
        }

        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')->label('التاريخ'),
                                Body\TextColumn::make('type')->label('نوع المعاملة'),
                                Body\TextColumn::make('quantity')->label('الكمية'),
                                Body\TextColumn::make('stock')->label('المخزون'),
                                Body\TextColumn::make("notes")
                                ->label("الملاحظات")
                                ->formatStateUsing(fn ($state) => strip_tags($state)),
                            ])
                            ->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');
                                    }

                                    if (! isset($filters['product_id']) || ! is_string($filters['product_id'])) {
                                        return collect([]);
                                    }

                                    $productId = $filters['product_id'];

                                    if (! isset($filters['date']) || ! is_string($filters['date'])) {
                                        return collect([]);
                                    }

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

                                    if (! $from || ! $to) {
                                        return collect([]);
                                    }

                                    // Get initial stock
                                    $product = Product::find($productId);
                                    if (! $product) {
                                        return collect([]);
                                    }

                                    $initialStock = $product->stock;
                                    // dd($initialStock);
                                    // Subtract sales before the date range
                                    $salesBefore = Sale::whereHas('products', function ($query) use ($productId) {
                                        $query->where('products.id', $productId);
                                    })->where('sales.date', '<', $from)->get();

                                    $initialStock -= $salesBefore->reduce(function ($carry, $sale) use ($productId) {
                                        return $carry + $sale->products->find($productId)->pivot->quantity;
                                    }, 0);

                                    // Add purchases before the date range
                                    $purchasesBefore = Purchase::whereHas('products', function ($query) use ($productId) {
                                        $query->where('products.id', $productId);
                                    })->where('purchases.date', '<', $from)->get();

                                    $initialStock += $purchasesBefore->reduce(function ($carry, $purchase) use ($productId) {
                                        return $carry + $purchase->products->find($productId)->pivot->quantity;
                                    }, 0);

                                    // Transactions within the date range
                                    $sales = Sale::whereHas('products', function ($query) use ($productId) {
                                        $query->where('products.id', $productId);
                                    })->whereBetween('sales.date', [$from, $to])->get();

                                    $purchases = Purchase::whereHas('products', function ($query) use ($productId) {
                                        $query->where('products.id', $productId);
                                    })->whereBetween('purchases.date', [$from, $to])->get();

                                    // Merge transactions
                                    $transactions = collect([[ // Initial stock entry
                                        'date' => $from->subDay()->format('Y-m-d'),
                                        'type' => 'رصيد أول',
                                        'quantity' => 0,
                                        'stock' => $initialStock,
                                        'notes' => 'رصيد أول',
                                    ]]);

                                    $transactions = $transactions->merge($sales->map(function ($sale) use ($productId) {
                                        return [
                                            'date' => $sale->date,
                                            'type' => 'صرف',
                                            'quantity' => -$sale->products->find($productId)->pivot->quantity,
                                            'notes' => $sale->notes ?? '',
                                        ];
                                    }));

                                    $transactions = $transactions->merge($purchases->map(function ($purchase) use ($productId) {
                                        return [
                                            'date' => $purchase->date,
                                            'type' => 'وارد',
                                            'quantity' => $purchase->products->find($productId)->pivot->quantity,
                                            'notes' => $purchase->notes ?? '',
                                        ];
                                    }));

                                    // Sort transactions by date
                                    $transactions = $transactions->sortBy('date')->values();

                                    // Calculate running stock (balance)
                                    $stock = $initialStock;

                                    return $transactions->map(function ($transaction) use (&$stock) {
                                        $stock += $transaction['quantity']; // Adjust stock based on quantity

                                        return array_merge($transaction, ['stock' => $stock]);
                                    });
                                }

                            ),
                    ]),
            ]);
    }

    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('product_id')
                    ->label('المنتج')
                    ->options(
                        Product::all()->pluck('name', 'id')->toArray()
                    )
                    ->placeholder('حدد المنتج')
                    ->required()
                    ->preload(),
            ]);
    }
}
