<?php

namespace App\Filament\Resources\ResellerOrders\Pages;

use App\Filament\Resources\ResellerOrders\ResellerOrderResource;
use App\Models\Order;
use App\Models\OrderItem;
use App\Models\Product;
use App\Models\ProductVariant;
use Filament\Actions\Action;
use Filament\Actions\DeleteAction;
use Filament\Forms\Components\Repeater;
use Filament\Forms\Components\TextInput;
use Filament\Forms\Components\Select;
use Filament\Forms\Components\Hidden;
use Filament\Forms\Components\Textarea;
use Filament\Forms\Components\Placeholder;
use Filament\Schemas\Components\Grid;
use Filament\Forms\Form;
use Filament\Resources\Pages\EditRecord;
use Illuminate\Support\Str;

class EditResellerOrder extends EditRecord
{
    protected static string $resource = ResellerOrderResource::class;

    protected function getHeaderActions(): array
    {
        return [
            Action::make('create_return')
                ->label('Create Return/Refund')
                ->icon('heroicon-o-arrow-uturn-left')
                ->color('warning')
                ->visible(fn () => $this->record->status === 'delivered')
                ->url(fn () => \App\Filament\Resources\ReturnRequestResource::getUrl('create', ['order_id' => $this->record->id])),

            Action::make('create_exchange')
                ->label('Create Exchange')
                ->icon('heroicon-o-arrow-path')
                ->color('success')
                ->visible(fn () => $this->record->status === 'delivered')
                ->modalHeading('Create Exchange Order')
                ->modalWidth('4xl')
                ->form([
                    Repeater::make('returned_items')
                        ->label('Returned Items')
                        ->schema([
                            TextInput::make('product_name')
                                ->label('Product')
                                ->readOnly()
                                ->dehydrated(true)
                                ->columnSpan(4),
                            TextInput::make('variant_details')
                                ->label('Variant')
                                ->readOnly()
                                ->dehydrated(true)
                                ->placeholder('—')
                                ->columnSpan(2),
                            TextInput::make('price')
                                ->label('Price')
                                ->numeric()
                                ->readOnly()
                                ->dehydrated(true)
                                ->prefix('৳')
                                ->columnSpan(2),
                            TextInput::make('ordered_qty')
                                ->label('Ordered Qty')
                                ->numeric()
                                ->readOnly()
                                ->dehydrated(true)
                                ->columnSpan(2),
                            TextInput::make('return_qty')
                                ->label('Return Qty')
                                ->numeric()
                                ->integer()
                                ->default(0)
                                ->minValue(0)
                                ->maxValue(fn ($get) => $get('ordered_qty'))
                                ->live()
                                ->columnSpan(2),
                            Hidden::make('order_item_id'),
                        ])
                        ->columns(12)
                        ->addable(false)
                        ->deletable(false),

                    Repeater::make('exchange_items')
                        ->label('Exchange Items (New items to send)')
                        ->schema([
                            Select::make('product_id')
                                ->label('Product')
                                ->options(Product::where('is_visible', true)->pluck('name', 'id'))
                                ->searchable()
                                ->required()
                                ->live()
                                ->afterStateUpdated(function ($state, callable $set) {
                                    $set('product_variant_id', null);
                                    if (!$state) {
                                        $set('price', 0.00);
                                        return;
                                    }
                                    $product = Product::find($state);
                                    $set('price', $product ? $product->price : 0.00);
                                })
                                ->columnSpan(4),
                            Select::make('product_variant_id')
                                ->label('Variant')
                                ->options(function ($get) {
                                    $productId = $get('product_id');
                                    if (!$productId) return [];
                                    return ProductVariant::where('product_id', $productId)
                                        ->get()
                                        ->mapWithKeys(function ($variant) {
                                            $optionsStr = collect($variant->options)
                                                ->map(fn($v, $k) => "$k: $v")
                                                ->implode(', ');
                                            return [$variant->id => $variant->sku . " ($optionsStr)"];
                                        });
                                })
                                ->searchable()
                                ->live()
                                ->afterStateUpdated(function ($state, callable $set, $get) {
                                    if (!$state) {
                                        $productId = $get('product_id');
                                        $product = Product::find($productId);
                                        $set('price', $product ? $product->price : 0.00);
                                        return;
                                    }
                                    $variant = ProductVariant::with('product')->find($state);
                                    $set('price', ($variant && $variant->price !== null && floatval($variant->price) > 0) ? $variant->price : ($variant ? $variant->product->price : 0.00));
                                })
                                ->columnSpan(4),
                            TextInput::make('price')
                                ->label('Unit Price')
                                ->numeric()
                                ->readOnly()
                                ->dehydrated(true)
                                ->prefix('৳')
                                ->columnSpan(2),
                            TextInput::make('quantity')
                                ->label('Qty')
                                ->numeric()
                                ->integer()
                                ->default(1)
                                ->minValue(1)
                                ->required()
                                ->live()
                                ->columnSpan(2),
                        ])
                        ->columns(12)
                        ->live(),

                    Grid::make(2)
                        ->schema([
                            TextInput::make('exchange_shipping_cost')
                                ->label('Exchange Delivery Charge')
                                ->numeric()
                                ->prefix('৳')
                                ->required()
                                ->live(),
                            TextInput::make('exchange_discount')
                                ->label('Exchange Discount')
                                ->numeric()
                                ->prefix('৳')
                                ->default(0.00)
                                ->live(),
                        ]),

                    Placeholder::make('summary')
                        ->label('Financial Summary')
                        ->content(function ($get) {
                            $returnedItems = collect($get('returned_items') ?? []);
                            $exchangeItems = collect($get('exchange_items') ?? []);
                            $shippingCost = (float) ($get('exchange_shipping_cost') ?? 0.00);
                            $exchangeDiscount = (float) ($get('exchange_discount') ?? 0.00);

                            $returnedValue = $returnedItems->sum(function ($item) {
                                $orderItem = OrderItem::find($item['order_item_id'] ?? null);
                                return $orderItem ? (float) $orderItem->price * (int) ($item['return_qty'] ?? 0) : 0.00;
                            });

                            $exchangeValue = $exchangeItems->sum(function ($item) {
                                $productId = $item['product_id'] ?? null;
                                if (!$productId) return 0.00;

                                $variantId = $item['product_variant_id'] ?? null;
                                if ($variantId) {
                                    $variant = ProductVariant::with('product')->find($variantId);
                                    $price = ($variant && $variant->price !== null && floatval($variant->price) > 0) ? (float) $variant->price : ($variant ? (float) $variant->product->price : 0.00);
                                } else {
                                    $product = Product::find($productId);
                                    $price = $product ? (float) $product->price : 0.00;
                                }
                                return $price * (int) ($item['quantity'] ?? 1);
                            });

                            $discount = $returnedValue + $exchangeDiscount;
                            $cod = max(0, $exchangeValue + $shippingCost - $discount);
                            $refund = max(0, $discount - $exchangeValue - $shippingCost);

                            $refundRow = '';
                            if ($refund > 0) {
                                $refundRow = "
                                    <span style='opacity: 0.7; color: #3b82f6;'>Refundable Amount:</span>
                                    <span style='font-weight: 600; color: #3b82f6; text-align: right;'>৳" . number_format($refund, 2) . "</span>
                                ";
                            }

                            return new \Illuminate\Support\HtmlString("
                                <div style='padding: 1.25rem; background: rgba(128, 128, 128, 0.05); border: 1px solid rgba(128, 128, 128, 0.15); border-radius: 0.75rem; font-family: inherit; color: inherit; width: 100%; box-sizing: border-box;'>
                                    <h3 style='margin: 0 0 1rem 0; font-size: 0.95rem; font-weight: 700; text-transform: uppercase; letter-spacing: 0.05em; opacity: 0.8; border-bottom: 1px dashed rgba(128, 128, 128, 0.25); padding-bottom: 0.5rem;'>
                                        Financial Summary
                                    </h3>
                                    <div style='display: grid; grid-template-columns: 1fr auto; gap: 0.75rem; font-size: 0.875rem; line-height: 1.25rem;'>
                                        
                                        <span style='opacity: 0.7;'>Total Returned Value (Credit):</span>
                                        <span style='font-weight: 600; text-align: right;'>৳" . number_format($returnedValue, 2) . "</span>
                                        
                                        <span style='opacity: 0.7;'>Total Exchanged Value (New Items):</span>
                                        <span style='font-weight: 600; text-align: right;'>৳" . number_format($exchangeValue, 2) . "</span>
                                        
                                        <span style='opacity: 0.7;'>Exchange Delivery Charge:</span>
                                        <span style='font-weight: 600; text-align: right;'>+ ৳" . number_format($shippingCost, 2) . "</span>
                                        
                                        <span style='opacity: 0.7;'>Additional Discount:</span>
                                        <span style='font-weight: 600; color: #ef4444; text-align: right;'>- ৳" . number_format($exchangeDiscount, 2) . "</span>
                                        
                                        {$refundRow}
                                        
                                        <div style='grid-column: span 2; border-top: 2px solid rgba(128, 128, 128, 0.15); margin: 0.5rem 0; padding-top: 0.75rem; display: grid; grid-template-columns: 1fr auto; align-items: center;'>
                                            <span style='font-size: 1rem; font-weight: 800;'>Total COD to Collect:</span>
                                            <span style='font-size: 1.25rem; font-weight: 800; color: #22c55e; text-align: right;'>৳" . number_format($cod, 2) . "</span>
                                        </div>
                                    </div>
                                </div>
                            ");
                        })
                        ->columnSpanFull(),

                    Select::make('reason')
                        ->label('Reason for Exchange')
                        ->options([
                            'size_issue' => 'Size Issue',
                            'wrong_item' => 'Wrong Item Delivered',
                            'damaged' => 'Damaged Product',
                            'other' => 'Other / Change of Mind',
                        ])
                        ->default('size_issue')
                        ->required(),

                    Textarea::make('reason_details')
                        ->label('Additional Details')
                        ->placeholder('e.g., color discrepancy, exact size requirements')
                        ->rows(2),
                ])
                ->mountUsing(function ($form) {
                    $form->fill([
                        'returned_items' => $this->record->items->map(function ($item) {
                            $optionsStr = '';
                            if ($item->product_variant_id && $item->variant) {
                                $optionsStr = collect($item->variant->options)
                                    ->map(fn($v, $k) => "$k: $v")
                                    ->implode(', ');
                            }
                            return [
                                'order_item_id' => $item->id,
                                'product_name' => $item->product_name,
                                'variant_details' => !empty($optionsStr) ? $optionsStr : '—',
                                'price' => $item->price,
                                'ordered_qty' => $item->quantity,
                                'return_qty' => 0,
                            ];
                        })->toArray(),
                        'exchange_shipping_cost' => $this->record->shipping_cost,
                        'exchange_discount' => 0.00,
                    ]);
                })
                ->action(function (array $data) {
                    $originalOrder = $this->record;

                    // 1. Validate that at least one item is being returned AND at least one item is being exchanged
                    $returnedItems = collect($data['returned_items'])->filter(fn ($item) => $item['return_qty'] > 0);
                    $exchangeItems = collect($data['exchange_items']);

                    if ($returnedItems->isEmpty()) {
                        \Filament\Notifications\Notification::make()
                            ->title('Validation Error')
                            ->body('Please select at least one item and quantity to return.')
                            ->danger()
                            ->send();
                        return;
                    }

                    if ($exchangeItems->isEmpty()) {
                        \Filament\Notifications\Notification::make()
                            ->title('Validation Error')
                            ->body('Please add at least one exchange item to send.')
                            ->danger()
                            ->send();
                        return;
                    }

                    // 2. Calculate Returned Items Value safely from original order items in DB
                    $returnedValue = $returnedItems->sum(function ($item) {
                        $orderItem = OrderItem::find($item['order_item_id']);
                        return $orderItem ? (float) $orderItem->price * (int) $item['return_qty'] : 0.00;
                    });

                    // 3. Create ReturnRequest in database
                    $returnRequest = \App\Models\ReturnRequest::create([
                        'order_id' => $originalOrder->id,
                        'user_id' => $originalOrder->user_id,
                        'status' => 'approved', 
                        'type' => 'return', // Return/Exchange
                        'reason' => $data['reason'] ?? 'size_issue',
                        'customer_notes' => 'Exchange request created by administrator.' . 
                            (!empty($data['reason_details']) ? ' Details: ' . $data['reason_details'] : ''),
                        'exchange_shipping_cost' => (float) $data['exchange_shipping_cost'],
                    ]);

                    // Save returned items to return_request_items
                    foreach ($returnedItems as $item) {
                        \App\Models\ReturnRequestItem::create([
                            'return_request_id' => $returnRequest->id,
                            'order_item_id' => $item['order_item_id'],
                            'quantity' => $item['return_qty'],
                            'price' => $item['price'],
                        ]);
                    }

                    // 4. Create New Order (Exchange Order)
                    $exchangeOrder = Order::create([
                        'user_id' => $originalOrder->user_id,
                        'customer_name' => $originalOrder->customer_name,
                        'customer_email' => $originalOrder->customer_email,
                        'customer_phone' => $originalOrder->customer_phone,
                        'shipping_address' => $originalOrder->shipping_address,
                        'billing_address' => $originalOrder->billing_address,
                        'street_address' => $originalOrder->street_address,
                        'city' => $originalOrder->city,
                        'state' => $originalOrder->state,
                        'zip' => $originalOrder->zip,
                        'country' => $originalOrder->country,
                        'shipping_method_id' => $originalOrder->shipping_method_id,
                        'is_exchange' => true,
                        'parent_order_id' => $originalOrder->id,
                        'status' => 'pending',
                        'payment_method' => 'cod', // COD for exchange difference
                        'payment_status' => 'pending',
                        'shipping_cost' => (float) $data['exchange_shipping_cost'],
                        'subtotal' => 0.00,
                        'discount' => 0.00,
                        'grand_total' => 0.00,
                        'notes' => 'Exchange Order for #' . $originalOrder->order_number . '. Reason: ' . ($data['reason'] ?? 'N/A'),
                    ]);

                    // Populate items for new Order and calculate subtotal
                    $subtotal = 0.00;
                    foreach ($exchangeItems as $item) {
                        $product = Product::find($item['product_id']);
                        $variant = $item['product_variant_id'] ? ProductVariant::with('product')->find($item['product_variant_id']) : null;
                         
                        $price = ($variant && $variant->price !== null && floatval($variant->price) > 0) ? (float) $variant->price : (float) $product->price;
                        $qty = (int) $item['quantity'];
                        $subtotal += $price * $qty;

                        // Get options string if variant exists
                        $optionsStr = '';
                        if ($variant && $variant->options) {
                            $optionsStr = ' (' . collect($variant->options)->map(fn($v, $k) => "$k: $v")->implode(', ') . ')';
                        }

                        $exchangeOrder->items()->create([
                            'product_id' => $product->id,
                            'product_variant_id' => $variant?->id,
                            'product_name' => $product->name . $optionsStr,
                            'product_sku' => $variant ? $variant->sku : $product->sku,
                            'price' => $price,
                            'quantity' => $qty,
                        ]);

                        // Save to exchange_request_items table
                        \App\Models\ExchangeRequestItem::create([
                            'return_request_id' => $returnRequest->id,
                            'product_id' => $product->id,
                            'product_variant_id' => $variant?->id,
                            'quantity' => $qty,
                            'price' => $price,
                        ]);
                    }

                    // Calculate totals
                    $shippingCost = (float) $data['exchange_shipping_cost'];
                    $additionalDiscount = (float) ($data['exchange_discount'] ?? 0.00);
                    $discount = $returnedValue + $additionalDiscount;
                    $grandTotal = max(0, $subtotal + $shippingCost - $discount);

                    // Link the exchange order back to return request first
                    $returnRequest->update([
                        'exchange_order_id' => $exchangeOrder->id,
                    ]);

                    // Update exchange order totals (this will trigger Order saved observer to calculate and sync refund details)
                    $exchangeOrder->update([
                        'subtotal' => $subtotal,
                        'discount' => $discount,
                        'grand_total' => $grandTotal,
                    ]);

                    // Add history logs
                    $originalOrder->histories()->create([
                        'user_id' => auth()->id(),
                        'action' => 'status_changed',
                        'from_status' => $originalOrder->status,
                        'to_status' => $originalOrder->status,
                        'notes' => 'Exchange request created. New Exchange Order: #' . $exchangeOrder->order_number,
                    ]);

                    $exchangeOrder->histories()->create([
                        'user_id' => auth()->id(),
                        'action' => 'order_created',
                        'from_status' => null,
                        'to_status' => 'pending',
                        'notes' => 'Exchange Order created from original Order #' . $originalOrder->order_number,
                    ]);

                    \Filament\Notifications\Notification::make()
                        ->title('Exchange Order Created')
                        ->body("Exchange order: {$exchangeOrder->order_number} (COD: ৳{$grandTotal})")
                        ->success()
                        ->send();

                    // Redirect to the new exchange order
                    $this->redirect(static::getResource()::getUrl('edit', ['record' => $exchangeOrder->id]));
                }),

            Action::make('view_invoice')
                ->label('Invoice')
                ->icon('heroicon-o-document-text')
                ->color('gray')
                ->url(fn () => route('orders.invoice', ['order' => $this->record->id]))
                ->openUrlInNewTab(),

            Action::make('replicate')
                ->label('Replicate')
                ->icon('heroicon-o-document-duplicate')
                ->color('gray')
                ->requiresConfirmation()
                ->modalHeading('Replicate order?')
                ->modalDescription('A new order will be created with the same items and customer information.')
                ->action(function () {
                    $record = $this->record;
                    $newRecord = $record->replicate();
                    $newRecord->order_number = 'SB-' . strtoupper(Str::random(3)) . '-' . date('ymdHis');
                    $newRecord->status = 'pending';
                    $newRecord->save();

                    foreach ($record->items as $item) {
                        $newItem = $item->replicate();
                        $newItem->order_id = $newRecord->id;
                        $newItem->save();
                    }

                    $newRecord->histories()->create([
                        'user_id'     => auth()->id(),
                        'action'      => 'order_created',
                        'from_status' => null,
                        'to_status'   => 'pending',
                        'notes'       => 'Order replicated from #' . $record->order_number . ' by administrator.',
                    ]);

                    \Filament\Notifications\Notification::make()
                        ->title('Order Replicated')
                        ->body("New order: {$newRecord->order_number}")
                        ->success()
                        ->send();

                    $this->redirect(static::getResource()::getUrl('edit', ['record' => $newRecord->id]));
                }),

            DeleteAction::make()
                ->icon('heroicon-o-trash'),
        ];
    }

    public ?string $oldStatus = null;
    public ?string $oldPaymentStatus = null;

    protected function beforeSave(): void
    {
        $this->oldStatus = $this->record->getOriginal('status');
        $this->oldPaymentStatus = $this->record->getOriginal('payment_status');
    }

    protected function afterSave(): void
    {
        $order = $this->record;

        // Track order status changes
        if ($order->wasChanged('status')) {
            $newStatus = $order->status;
            $oldStatus = $this->oldStatus;

            $order->histories()->create([
                'user_id'     => auth()->id(),
                'action'      => 'status_changed',
                'from_status' => $oldStatus,
                'to_status'   => $newStatus,
                'notes'       => 'Status updated to ' . $newStatus . ' by administrator.',
            ]);

            try {
                \App\Services\NotificationDispatcher::dispatchForOrder($order, $newStatus);
            } catch (\Exception $e) {
                \Illuminate\Support\Facades\Log::error('Order notification dispatch failed: ' . $e->getMessage());
            }
        }

        // Track payment status changes
        if ($order->wasChanged('payment_status')) {
            $newPaymentStatus = $order->payment_status;
            $oldPaymentStatus = $this->oldPaymentStatus;

            $order->histories()->create([
                'user_id'     => auth()->id(),
                'action'      => 'payment_updated',
                'from_status' => $oldPaymentStatus,
                'to_status'   => $newPaymentStatus,
                'notes'       => 'Payment status updated to ' . $newPaymentStatus . ' by administrator.',
            ]);

            // Dispatch notification if payment status changed
            try {
                if ($newPaymentStatus === 'paid' && $oldPaymentStatus !== 'paid') {
                    \App\Services\NotificationDispatcher::dispatchPaymentReceived($order);
                } elseif ($newPaymentStatus === 'failed' && $oldPaymentStatus !== 'failed') {
                    \App\Services\NotificationDispatcher::dispatchPaymentFailed($order);
                } elseif ($newPaymentStatus === 'refunded' && $oldPaymentStatus !== 'refunded') {
                    \App\Services\NotificationDispatcher::dispatchPaymentRefunded($order);
                }
            } catch (\Exception $e) {
                \Illuminate\Support\Facades\Log::error('Payment notification dispatch failed: ' . $e->getMessage());
            }
        }
    }
}
