<?php

namespace App\Filament\Resources\OrderResource\Components;

use App\Filament\Resources\OrderResource;
use App\Models\Order;
use App\Models\OrderRequirement;
use Carbon\Carbon;
use Filament\Actions;
use Filament\Forms;
use Filament\Forms\Components\Textarea;
use Filament\Notifications\Notification;
use Guava\FilamentModalRelationManagers\Actions\Action\RelationManagerAction;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\HtmlString;

class OrderApprovalFlow
{
    public static function getApprovalFlowActions(Order $record): array
    {
        $actions = [];

        $nextStatus = $record->getNextStatus();
        $permissionMap = [
            Order::STATUS_PENDING_RECOMMENDATION => 'request_order_recommendation_order',
            Order::STATUS_RECOMMENDED => 'provide_order_recommendation_order',
            Order::STATUS_TECHNICAL_FINANCIAL_REQUESTED => 'request_technical_financial_proposal_order',
            Order::STATUS_TECHNICAL_FINANCIAL_APPROVED => 'approve_technical_financial_proposal_order',
            Order::STATUS_PROJECT_MANAGER_APPROVED => 'approve_project_manager_order',
            Order::STATUS_CLASSIFICATION => 'handle_classification_order',
            Order::STATUS_AGREEMENT => 'handle_agreement_order',
            Order::STATUS_CEO_APPROVED => 'approve_ceo_order',
            Order::STATUS_LAUNCHED => 'launch_project_order',
            Order::STATUS_ACCEPTED => 'accept_order_order',
        ];

        $requiredPermission = $permissionMap[$nextStatus] ?? null;

        if ($requiredPermission && Auth::user()->can($requiredPermission)) {

            $actions[] = Actions\Action::make('approve')
                ->label($record->status !== Order::STATUS_RECOMMENDED ? __('order.approve') : __('order.recommend'))
                ->icon('heroicon-o-check-circle')
                ->color('success')
                ->form(self::getForms($record))
                ->action(function (array $data) use ($record) {
                    return self::getActions($data, $record);
                });

            // Add send back action if order can be sent back
            if ($record->canSendBackToPreviousStage()) {
                $actions[] = Actions\Action::make('send_back')
                    ->label(__('order.send_back'))
                    ->icon('heroicon-o-arrow-right')
                    ->color('warning')
                    ->requiresConfirmation()
                    ->modalHeading(__('order.send_back_confirmation'))
                    ->modalDescription(__('order.send_back_description'))
                    ->form([
                        Textarea::make('notes')
                            ->label(__('order.send_back_notes'))
                            ->required()
                            ->rows(3)
                            ->helperText(__('order.send_back_notes_helper')),
                    ])
                    ->action(function (array $data) use ($record) {
                        if ($record->sendBackToPreviousStage($data['notes'])) {
                            Notification::make()
                                ->title(__('order.order_sent_back_successfully'))
                                ->success()
                                ->send();

                            return redirect(OrderResource::getUrl('view', ['record' => $record]));
                        } else {
                            Notification::make()
                                ->title(__('order.send_back_failed'))
                                ->danger()
                                ->send();
                        }
                    });
            }

            if ($record->status === Order::STATUS_CLASSIFICATION) {
                $actions[] = RelationManagerAction::make('donor-financial-portfolios')
                    ->label(__('donor_financial_portfolio.assign_to_portfolio'))
                    ->record($record)
                    ->relationManager(OrderResource\RelationManagers\DonorFinancialPortfoliosRelationManager::make());
            }

            if ($record->status !== Order::STATUS_RECOMMENDED) {
                $actions[] = Actions\Action::make('reject')
                    ->label(__('order.reject'))
                    ->icon('heroicon-o-x-circle')
                    ->color('danger')
                    ->form([
                        Textarea::make('notes')
                            ->label(__('order.rejection_notes'))
                            ->required()
                            ->rows(3),
                    ])
                    ->action(function (array $data) use ($record) {
                        // Check if order has allocated funding before rejection
                        $allocatedPortfolios = $record->donorFinancialPortfolios()->get();
                        $hasAllocatedFunding = $allocatedPortfolios->isNotEmpty();

                        $record->reject($data['notes']);

                        // Show appropriate notification based on funding status
                        if ($hasAllocatedFunding) {
                            Notification::make()
                                ->title(__('order.order_rejected'))
                                ->body(__('donor_financial_portfolio.order_rejected_funds_deallocated'))
                                ->success()
                                ->send();
                        } else {
                            Notification::make()
                                ->title(__('order.order_rejected'))
                                ->success()
                                ->send();
                        }
                    });
            }
        }

        return $actions;
    }

    private static function getForms(Order $record): array
    {
        $forms = [];

        switch ($record->status) {
            case Order::STATUS_TECHNICAL_FINANCIAL_APPROVED:
                $forms[] = Forms\Components\Section::make(__('order_finance.order_finance'))
                    ->schema([
                        Forms\Components\TextInput::make('count')
                            ->label(__('order_finance.count'))
                            ->numeric()
                            ->required()
                            ->helperText(__('order_finance.count_helper')),

                        Forms\Components\TextInput::make('capacity')
                            ->label(__('order_finance.capacity'))
                            ->maxLength(255)
                            ->required()
                            ->helperText(__('order_finance.capacity_helper')),

                        Forms\Components\TextInput::make('execution_duration')
                            ->label(__('order_finance.execution_duration'))
                            ->numeric()
                            ->required()
                            ->suffix(__('order_finance.days'))
                            ->helperText(__('order_finance.execution_duration_helper')),

                        Forms\Components\TextInput::make('company_name')
                            ->label(__('order_finance.company_name'))
                            ->maxLength(255)
                            ->required()
                            ->helperText(__('order_finance.company_name_helper')),

                        Forms\Components\Select::make('order_requirement_id')
                            ->label(__('order.approved_order_requirement'))
                            ->options(function () use ($record) {
                                return $record->requirements()
                                    ->where('status', OrderRequirement::STATUS_ACCEPTED)
                                    ->pluck('name', 'id')
                                    ->toArray();
                            })
                            ->required()
                            ->searchable(),

                        Forms\Components\Grid::make(2)
                            ->schema([
                                Forms\Components\TextInput::make('offer_price')
                                    ->label(__('order_finance.offer_price'))
                                    ->numeric()
                                    ->step(0.01)
                                    ->required()
                                    ->prefix(new HtmlString('<span class="icon-saudi_riyal"></span>'))
                                    ->live()
                                    ->helperText(__('order_finance.offer_price_helper')),

                                Forms\Components\TextInput::make('additional_fees')
                                    ->label(__('order_finance.additional_fees'))
                                    ->numeric()
                                    ->step(0.01)
                                    ->required()
                                    ->prefix(new HtmlString('<span class="icon-saudi_riyal"></span>'))
                                    ->live()
                                    ->helperText(__('order_finance.additional_fees_helper')),
                            ]),

                        Forms\Components\Placeholder::make('approved_price')
                            ->label(__('order_finance.approved_price'))
                            ->content(function (Forms\Get $get) {
                                $offerPrice = (float) ($get('offer_price') ?? 0);
                                $additionalFees = (float) ($get('additional_fees') ?? 0);

                                return $offerPrice + $additionalFees;
                            })
                            ->helperText(__('order_finance.approved_price_helper')),

                        Forms\Components\Hidden::make('operation_cost_percentage')
                            ->default(fn () => 0),
                    ])
                    ->columns(1);
                break;

            case Order::STATUS_AGREEMENT:
                $forms[] = Forms\Components\Section::make(__('order_agreement.order_agreement'))
                    ->schema([
                        Forms\Components\TextInput::make('contract_number')
                            ->label(__('order_agreement.contract_number'))
                            ->required()
                            ->maxLength(255)
                            ->unique(table: 'order_agreements', column: 'contract_number')
                            ->helperText(__('order_agreement.contract_number_helper')),

                        Forms\Components\TextInput::make('total_contract_value')
                            ->label(__('order_agreement.total_contract_value'))
                            // set default value to the approved price from finance
                            ->default(function (Order $record) {
                                return $record->finance?->approved_price ?? 0;
                            })
                            ->readOnly()
                            ->numeric()
                            ->step(0.01)
                            ->required()
                            ->prefix(new HtmlString('<span class="icon-saudi_riyal"></span>'))
                            ->helperText(__('order_agreement.total_contract_value_helper')),

                        Forms\Components\DatePicker::make('start_date')
                            ->label(__('order_agreement.start_date'))
                            ->required()
                            ->live()
                            ->afterStateUpdated(function (Forms\Set $set, $state) use ($record) {
                                if ($state && $record->finance?->execution_duration) {
                                    $startDate = \Carbon\Carbon::parse($state);
                                    $endDate = $startDate->addDays($record->finance->execution_duration);
                                    $set('calculated_end_date', $endDate->format('Y-m-d'));
                                }
                            })
                            ->helperText(__('order_agreement.start_date_helper')),

                        Forms\Components\Hidden::make('calculated_end_date'),

                        Forms\Components\Placeholder::make('end_date_display')
                            ->label(__('order_agreement.end_date'))
                            ->content(function (Forms\Get $get) use ($record) {
                                $calculatedEndDate = $get('calculated_end_date');
                                if ($calculatedEndDate) {
                                    return \Carbon\Carbon::parse($calculatedEndDate)->format('Y-m-d');
                                }

                                $startDate = $get('start_date');
                                if ($startDate && $record->finance?->execution_duration) {
                                    $start = \Carbon\Carbon::parse($startDate);
                                    $end = $start->addDays($record->finance->execution_duration);

                                    return $end->format('Y-m-d');
                                }

                                return __('order_agreement.not_calculated');
                            })
                            ->helperText(__('order_agreement.end_date_helper').' ('.($record->finance?->execution_duration ?? 0).' '.__('order_finance.days').')'),

                        Forms\Components\SpatieMediaLibraryFileUpload::make('order_agreement.agreement_file')
                            ->label(__('order_agreement.agreement_file'))
                            ->collection('agreement_file')
                            ->visibility('private')
                            ->directory('order-agreements')
                            ->acceptedFileTypes(['application/pdf'])
                            ->downloadable()
                            ->maxSize(10240) // 10MB
                            ->required()
                            ->helperText(__('order_agreement.agreement_file_helper'))
                            ->columnSpanFull(),
                    ])
                    ->columns(2);
                break;

            case Order::STATUS_RECOMMENDED:
                // show recommendation form with approve or reject select and notes form
                $forms[] = Forms\Components\Section::make()
                    ->schema([
                        Forms\Components\Radio::make('recommendation')
                            ->label(__(''))
                            ->options([
                                'approve' => __('order.approve'),
                                'reject' => __('order.reject'),
                            ])
                            ->inline()
                            ->live()
                            ->required(),

                        Forms\Components\Textarea::make('notes')
                            ->label(__('order.recommendation'))
                            ->visible(fn ($get) => $get('recommendation') === 'reject')
                            ->required(fn ($get) => $get('recommendation') === 'reject'),
                    ]);
                break;

            case Order::STATUS_CEO_APPROVED:
                $forms[] = Forms\Components\Section::make(__('order_agreement.order_agreement'))
                    ->schema([
                        Forms\Components\SpatieMediaLibraryFileUpload::make('agreement_file')
                            ->label(__('order_agreement.agreement_file'))
                            ->collection('agreement_file')
                            ->visibility('private')
                            ->directory('order-agreements')
                            ->acceptedFileTypes(['application/pdf'])
                            ->downloadable()
                            ->maxSize(10240) // 10MB
                            ->required()
                            ->helperText(__('order_agreement.agreement_file_helper'))
                            ->columnSpanFull(),

                        Forms\Components\Placeholder::make('order_agreement.agreement_file')
                            ->label(__(''))
                            ->content(fn (Order $record): HtmlString => new HtmlString('<a class="text-blue-500 hover:underline" href="'.$record->getAgreementFile()?->getTemporaryUrl(Carbon::now()->addMinutes(5)).'" target="_blank">'.
                                __('order_agreement.download_agreement_file').'</a>')),
                    ]);
                break;

            default:
                break;
        }

        return $forms;
    }

    private static function getActions(array $data, Order $record)
    {
        switch ($record->status) {
            case Order::STATUS_TECHNICAL_FINANCIAL_APPROVED:
                // Extract finance data
                $financeData = collect($data)->except('notes')->toArray();

                // Create finance record
                $record->finance()->create($financeData);
                break;

            case Order::STATUS_AGREEMENT:
                // Extract agreement data (exclude file upload and display fields)
                $agreementData = collect($data)->except([
                    'notes',
                    'execution_duration_display',
                    'end_date_display',
                    'calculated_end_date',
                    'agreement_file',
                ])->toArray();

                // Add order_id to agreement data
                $agreementData['order_id'] = $record->id;

                // Create agreement record
                $agreement = $record->agreement()->create($agreementData);

                // Handle file upload if provided
                if (! empty($data['agreement_file'])) {
                    // The SpatieMediaLibraryFileUpload component handles the file automatically
                    // when creating the record, but since we're creating manually, we need to handle it
                    // The file is already uploaded, we just need to associate it with the agreement
                }
                break;

            case Order::STATUS_RECOMMENDED:
                $recommendation = $data['recommendation'] ?? null;
                $data['notes'] = __('order.'.$recommendation).': '.($data['notes'] ?? '');
                break;

            case Order::STATUS_CLASSIFICATION:
                /**
                 * for example:
                 * $approvedPrice = $order->finance?->approved_price ?? 0;
                 * $currentTotal = $order->getTotalAllocatedFunding();
                 * $remainingAmount = $approvedPrice - $currentTotal;
                 * $remainingPercentage = $approvedPrice > 0 ? ($remainingAmount / $approvedPrice) * 100 : 0;
                 *
                 * then if remainingAmount is more than 0, show a notification error that he must allocate funds
                 * before approving the order
                 */
                $approvedPrice = $record->finance?->approved_price ?? 0;
                $currentTotal = $record->getTotalAllocatedFunding();
                $remainingAmount = $approvedPrice - $currentTotal;
                $remainingPercentage = $approvedPrice > 0 ? ($remainingAmount / $approvedPrice) * 100 : 0;

                if ($remainingAmount > 0) {
                    Notification::make()
                        ->title(__('donor_financial_portfolio.remaining_funding_needed').': '.$remainingAmount.' ريال ('.number_format($remainingPercentage, 2).'%)')
                        ->danger()
                        ->send();

                    return null; // Prevent further actions if funding is not sufficient
                }
                break;

            default:

                break;
        }

        if ($record->isTherePendingRequirements()) {
            Notification::make()
                ->title(__('order.order_requirements_pending'))
                ->danger()
                ->send();
        } elseif ($record->approveToNextStage($data['notes'] ?? '')) {
            Notification::make()
                ->title(__('order.order_approved_successfully'))
                ->success()
                ->send();

            return redirect(OrderResource::getUrl('view', ['record' => $record]));
        } else {
            Notification::make()
                ->title(__('order.approval_failed'))
                ->danger()
                ->send();
        }

        return null;
    }
}
