<?php

namespace App\Models;

use Carbon\Carbon;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\Relations\HasOne;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Log;
use Monzer\FilamentWorkflows\Traits\TrackWorkflowModelEvents;
use Spatie\Activitylog\LogOptions;
use Spatie\Activitylog\Models\Activity;
use Spatie\Activitylog\Traits\LogsActivity;
use Spatie\MediaLibrary\HasMedia;
use Spatie\MediaLibrary\InteractsWithMedia;
use Spatie\MediaLibrary\MediaCollections\Models\Media;

class Order extends Model implements HasMedia
{
    use HasFactory, InteractsWithMedia, LogsActivity, TrackWorkflowModelEvents;

    const TYPE_STATION = 'STATION';

    const TYPE_TANKER = 'TANKER';

    const TYPE_DOMESTIC_STORAGE_TANK = 'STORAGE_TANK';

    const TYPE_CENTRAL_STORAGE_TANK = 'CENTRAL_STORAGE_TANK';

    const TYPE_MAINTENANCE_STATION = 'MAINTENANCE_STATION';

    const TYPE_MAINTENANCE_TANKER = 'MAINTENANCE_TANKER';

    const TYPE_MICRO_NETWORK = 'MICRO_NETWORK';

    const TYPE_OTHER = 'OTHER';

    const TYPE_WELL_DRILLING = 'WELL_DRILLING';

    const TYPE_RAINWATER_STORAGE = 'RAINWATER_STORAGE';

    const TYPE_HOME_FILTERS = 'HOME_FILTERS';

    const TYPE_WATER_BOTTLES = 'WATER_BOTTLES';

    const TYPE_COOLERS = 'COOLERS';

    const TYPE_PRODUCTS_UNDER_REVIEW = 'PRODUCTS_UNDER_REVIEW';

    const TYPE_WELL_PURIFICATION_LICENSES = 'WELL_PURIFICATION_LICENSES';

    const WATER_SOURCE_GOVERNMENT = 'government';

    const WATER_SOURCE_PRIVATE = 'private';

    const WATER_SOURCE_CHARITY = 'charity';

    const STATUS_CREATED = 'CREATED';

    const STATUS_PENDING_RECOMMENDATION = 'PENDING_RECOMMENDATION';

    const STATUS_RECOMMENDED = 'RECOMMENDED';

    const STATUS_TECHNICAL_FINANCIAL_REQUESTED = 'TECHNICAL_FINANCIAL_REQUESTED';

    const STATUS_TECHNICAL_FINANCIAL_APPROVED = 'TECHNICAL_FINANCIAL_APPROVED';

    const STATUS_PROJECT_MANAGER_APPROVED = 'PROJECT_MANAGER_APPROVED';

    const STATUS_CLASSIFICATION = 'CLASSIFICATION';

    const STATUS_AGREEMENT = 'AGREEMENT';

    const STATUS_CEO_APPROVED = 'CEO_APPROVED';

    const STATUS_LAUNCHED = 'LAUNCHED';

    const STATUS_ACCEPTED = 'ACCEPTED';

    const STATUS_REJECTED = 'REJECTED';

    protected $fillable = [
        'type',
        'status',
        'created_by',
        'association_id',
        'state_id',
        'city_id',
        'lat',
        'lng',
        'number_of_families',
        'water_source',
        'water_distance',
        'order_justifications',
        'order_description',
        'location',
    ];

    protected $appends = [
        'location',
    ];

    protected $casts = [
        'created_at' => 'datetime',
        'updated_at' => 'datetime',
        'number_of_families' => 'integer',
        'water_distance' => 'decimal:2',
        'lat' => 'decimal:8',
        'lng' => 'decimal:8',
        'water_source' => 'array',
    ];

    protected $attributes = [
        'status' => self::STATUS_CREATED,
    ];

    protected static function boot()
    {
        parent::boot();

        static::creating(function ($model) {
            if (Auth::check()) {
                $model->created_by = Auth::id();
            }
        });
    }

    public function association(): BelongsTo
    {
        return $this->belongsTo(Association::class);
    }

    public function user(): BelongsTo
    {
        return $this->belongsTo(User::class, 'created_by');
    }

    public function state(): BelongsTo
    {
        return $this->belongsTo(State::class);
    }

    public function city(): BelongsTo
    {
        return $this->belongsTo(City::class);
    }

    public function centers(): BelongsToMany
    {
        return $this->belongsToMany(Center::class);
    }

    public function residentialGatherings(): BelongsToMany
    {
        return $this->belongsToMany(ResidentialGathering::class);
    }

    public function developmentImpacts(): BelongsToMany
    {
        return $this->belongsToMany(SekayaValue::class)
            ->where('type', SekayaValue::TYPE_ORDER_IMPACT_REASONS);
    }

    public function requirements(): HasMany
    {
        return $this->hasMany(OrderRequirement::class);
    }

    public function finance(): HasOne
    {
        return $this->hasOne(OrderFinance::class);
    }

    public function agreement(): HasOne
    {
        return $this->hasOne(OrderAgreement::class);
    }

    public function projectCharter(): HasOne
    {
        return $this->hasOne(ProjectCharter::class);
    }

    public function donorFinancialPortfolios(): BelongsToMany
    {
        return $this->belongsToMany(DonorFinancialPortfolio::class, 'donor_portfolio_order')
            ->withPivot([
                'allocated_amount',
            ])
            ->withTimestamps();
    }

    // an attribute to get the association email
    public function getAssociationEmailAttribute(): ?string
    {
        return $this->association ? $this->association->email : null;
    }

    /**
     * Get the total funding allocated to this order from all portfolios.
     * Only includes non-rejected orders to avoid counting invalid allocations.
     */
    public function getTotalAllocatedFunding(): float
    {
        // Only count allocations if this order is not rejected
        if ($this->status === self::STATUS_REJECTED) {
            return 0.0;
        }

        return $this->donorFinancialPortfolios()
            ->sum('donor_portfolio_order.allocated_amount');
    }

    /**
     * Get total operation cost which is calculated as follows:
     * - each donor has an operating_percentage
     * - the total operation cost is the sum of (allocated_amount * (operating_percentage / 100.0)) for each donor
     */
    public function getTotalOperationCostAttribute(): float
    {
        if (! $this->shouldShowOperationCost()) {
            return 0.0;
        }

        return $this->donorFinancialPortfolios()
            ->get()
            ->sum(fn ($portfolio) => $portfolio->pivot->allocated_amount * ($portfolio->operating_percentage / 100.0));
    }

    /**
     * return a bool that determine whether to show operation cost or not
     * which should be shown if the order's status is after STATUS_CLASSIFICATION
     */
    public function shouldShowOperationCost(): bool
    {
        return $this->status === self::STATUS_AGREEMENT
            || $this->status === self::STATUS_CEO_APPROVED
            || $this->status === self::STATUS_LAUNCHED
            || $this->status === self::STATUS_ACCEPTED;
    }

    /**
     * Get the file requirements for each order type
     */
    public static function getTypeFileRequirements(): array
    {
        return [
            self::TYPE_STATION => [
                'acceptance_criteria_for_micro_treatment_plant' => [
                    'label' => __('order.file_requirements.acceptance_criteria_for_micro_treatment_plant'),
                    'required' => true,
                    'file_url' => 'https://staging-marn-python.s3.amazonaws.com//sekaya/REQ-FILE_OEY0TQOUGYA7KHFP5OCS_.docx',
                ],
                'ownership_or_lease_agreement' => [
                    'label' => __('order.file_requirements.ownership_or_lease_agreement'),
                    'required' => true,
                    'file_url' => null,
                ],
                'well_disclosure' => [
                    'label' => __('order.file_requirements.well_disclosure'),
                    'required' => true,
                    'file_url' => null,
                ],
                'water_sample_analysis' => [
                    'label' => __('order.file_requirements.water_sample_analysis'),
                    'required' => true,
                    'file_url' => null,
                ],
                'project_land_buildings_plan' => [
                    'label' => __('order.file_requirements.project_land_buildings_plan'),
                    'required' => true,
                    'file_url' => null,
                ],
                'groundwater_usage_license' => [
                    'label' => __('order.file_requirements.groundwater_usage_license'),
                    'required' => false,
                    'file_url' => null,
                ],
            ],
            self::TYPE_TANKER => [
                'commercial_registration' => [
                    'label' => __('order.file_requirements.commercial_registration'),
                    'required' => true,
                    'file_url' => null,
                ],
            ],
            self::TYPE_DOMESTIC_STORAGE_TANK => [
                'home_tank_capacity' => [
                    'label' => __('order.file_requirements.home_tank_capacity'),
                    'required' => true,
                    'file_url' => 'https://staging-marn-python.s3.amazonaws.com//sekaya/REQ-FILE_TCACFDDRHOJ5WVXVQPE6_.docx',
                ],
            ],
            self::TYPE_CENTRAL_STORAGE_TANK => [
                'central_tank_capacity' => [
                    'label' => __('order.file_requirements.central_tank_capacity'),
                    'required' => true,
                    'file_url' => 'https://staging-marn-python.s3.amazonaws.com//sekaya/REQ-FILE_VOAFG7AUWJGIBKHBUX7M_.docx',
                ],
            ],
            self::TYPE_MAINTENANCE_STATION => [
                'ownership_or_lease_agreement' => [
                    'label' => __('order.file_requirements.ownership_or_lease_agreement'),
                    'required' => true,
                    'file_url' => null,
                ],
                'well_disclosure' => [
                    'label' => __('order.file_requirements.well_disclosure'),
                    'required' => false,
                    'file_url' => null,
                ],
                'station_technical_contract' => [
                    'label' => __('order.file_requirements.station_technical_contract'),
                    'required' => true,
                    'file_url' => null,
                ],
                'project_land_buildings_plan' => [
                    'label' => __('order.file_requirements.project_land_buildings_plan'),
                    'required' => true,
                    'file_url' => null,
                ],
                'water_sample_analysis' => [
                    'label' => __('order.file_requirements.water_sample_analysis'),
                    'required' => true,
                    'file_url' => null,
                ],
                'produced_water_analysis' => [
                    'label' => __('order.file_requirements.produced_water_analysis'),
                    'required' => true,
                    'file_url' => null,
                ],
                'operational_report' => [
                    'label' => __('order.file_requirements.operational_report'),
                    'required' => true,
                    'file_url' => 'https://staging-marn-python.s3.amazonaws.com//sekaya/REQ-FILE_ZRYWMRVLICXTRIG4C2AP_.docx',
                ],
            ],
            self::TYPE_MAINTENANCE_TANKER => [
                'tanker_driver_contract' => [
                    'label' => __('order.file_requirements.tanker_driver_contract'),
                    'required' => true,
                    'file_url' => null,
                ],
                'vehicle_registration' => [
                    'label' => __('order.file_requirements.vehicle_registration'),
                    'required' => true,
                    'file_url' => null,
                ],
                'vehicle_insurance' => [
                    'label' => __('order.file_requirements.vehicle_insurance'),
                    'required' => true,
                    'file_url' => null,
                ],
                'operational_report' => [
                    'label' => __('order.file_requirements.operational_report'),
                    'required' => true,
                    'file_url' => 'https://staging-marn-python.s3.amazonaws.com//sekaya/REQ-FILE_2545D1UPBSFOT8FRJ8A0_.docx',
                ],
            ],
            self::TYPE_MICRO_NETWORK => [
                'well_and_tank_land_concession' => [
                    'label' => __('order.file_requirements.well_and_tank_land_concession'),
                    'required' => true,
                    'file_url' => null,
                ],
                'well_water_analysis' => [
                    'label' => __('order.file_requirements.well_water_analysis'),
                    'required' => true,
                    'file_url' => null,
                ],
                'network_location_map' => [
                    'label' => __('order.file_requirements.network_location_map'),
                    'required' => true,
                    'file_url' => null,
                ],
                'project_feasibility_study' => [
                    'label' => __('order.file_requirements.project_feasibility_study'),
                    'required' => true,
                    'file_url' => null,
                ],
            ],
            self::TYPE_OTHER => [],
            self::TYPE_WELL_DRILLING => [],
            self::TYPE_RAINWATER_STORAGE => [],
            self::TYPE_HOME_FILTERS => [],
            self::TYPE_WATER_BOTTLES => [],
            self::TYPE_COOLERS => [],
            self::TYPE_PRODUCTS_UNDER_REVIEW => [],
            self::TYPE_WELL_PURIFICATION_LICENSES => [
                'well_purification_license_form' => [
                    'label' => __('order.file_requirements.well_purification_license_form'),
                    'required' => true,
                    'file_url' => 'https://sekaya-prod-api.fra1.digitaloceanspaces.com/sekaya-templates/%D9%86%D9%85%D9%88%D8%B0%D8%AC%20%D8%B7%D9%84%D8%A8%20%D8%AA%D8%B1%D8%AE%D9%8A%D8%B5%20%D8%A7%D9%84%D8%A2%D8%A8%D8%A7%D8%B1%20%20%D9%88%D9%85%D8%AD%D8%B7%D8%A7%D8%AA%20%D8%A7%D9%84%D8%AA%D9%86%D9%82%D9%8A%D8%A9.docx',
                ],
            ],
        ];
    }

    /**
     * Get the file requirements for this order's type
     */
    public function getFileRequirements(): array
    {
        return self::getTypeFileRequirements()[$this->type] ?? [];
    }

    /**
     * Get available order types
     */
    public static function getOrderTypes(): array
    {
        return [
            self::TYPE_STATION => __('order.station'),
            self::TYPE_TANKER => __('order.tanker'),
            self::TYPE_DOMESTIC_STORAGE_TANK => __('order.domestic_storage_tank'),
            self::TYPE_CENTRAL_STORAGE_TANK => __('order.central_storage_tank'),
            self::TYPE_MAINTENANCE_STATION => __('order.maintenance_station'),
            self::TYPE_MAINTENANCE_TANKER => __('order.maintenance_tanker'),
            self::TYPE_MICRO_NETWORK => __('order.micro_network'),
            self::TYPE_OTHER => __('order.other'),
            // self::TYPE_WELL_PURIFICATION_LICENSES => __('order.well_purification_licenses'),
            // self::TYPE_WELL_DRILLING => __('order.well_drilling'),
            // self::TYPE_RAINWATER_STORAGE => __('order.rainwater_storage'),
            // self::TYPE_HOME_FILTERS => __('order.home_filters'),
            // self::TYPE_WATER_BOTTLES => __('order.water_bottles'),
            // self::TYPE_COOLERS => __('order.coolers'),
            // self::TYPE_PRODUCTS_UNDER_REVIEW => __('order.products_under_review'),
        ];
    }

    /**
     * Get available order types
     */
    public static function getAllOrderTypes(): array
    {
        return [
            self::TYPE_STATION => __('order.station'),
            self::TYPE_TANKER => __('order.tanker'),
            self::TYPE_DOMESTIC_STORAGE_TANK => __('order.domestic_storage_tank'),
            self::TYPE_CENTRAL_STORAGE_TANK => __('order.central_storage_tank'),
            self::TYPE_MAINTENANCE_STATION => __('order.maintenance_station'),
            self::TYPE_MAINTENANCE_TANKER => __('order.maintenance_tanker'),
            self::TYPE_MICRO_NETWORK => __('order.micro_network'),
            self::TYPE_OTHER => __('order.other'),
            self::TYPE_WELL_DRILLING => __('order.well_drilling'),
            self::TYPE_RAINWATER_STORAGE => __('order.rainwater_storage'),
            self::TYPE_HOME_FILTERS => __('order.home_filters'),
            self::TYPE_WATER_BOTTLES => __('order.water_bottles'),
            self::TYPE_COOLERS => __('order.coolers'),
            self::TYPE_PRODUCTS_UNDER_REVIEW => __('order.products_under_review'),
            self::TYPE_WELL_PURIFICATION_LICENSES => __('order.well_purification_licenses'),
        ];
    }

    /**
     * Get product-specific count label
     */
    public function getProductCountLabel(): string
    {
        $productCountLabels = [
            self::TYPE_STATION => __('order.product_count_labels.station'),
            self::TYPE_TANKER => __('order.product_count_labels.tanker'),
            self::TYPE_DOMESTIC_STORAGE_TANK => __('order.product_count_labels.domestic_storage_tank'),
            self::TYPE_CENTRAL_STORAGE_TANK => __('order.product_count_labels.central_storage_tank'),
            self::TYPE_MAINTENANCE_STATION => __('order.product_count_labels.maintenance_station'),
            self::TYPE_MAINTENANCE_TANKER => __('order.product_count_labels.maintenance_tanker'),
            self::TYPE_MICRO_NETWORK => __('order.product_count_labels.micro_network'),
            self::TYPE_OTHER => __('order.product_count_labels.other'),
            self::TYPE_WELL_DRILLING => __('order.product_count_labels.well_drilling'),
            self::TYPE_RAINWATER_STORAGE => __('order.product_count_labels.rainwater_storage'),
            self::TYPE_HOME_FILTERS => __('order.product_count_labels.home_filters'),
            self::TYPE_WATER_BOTTLES => __('order.product_count_labels.water_bottles'),
            self::TYPE_COOLERS => __('order.product_count_labels.coolers'),
            self::TYPE_PRODUCTS_UNDER_REVIEW => __('order.product_count_labels.products_under_review'),
            self::TYPE_WELL_PURIFICATION_LICENSES => __('order.product_count_labels.well_purification_licenses'),
        ];

        return $productCountLabels[$this->type] ?? __('order_finance.count');
    }

    /**
     * Get product-specific capacity label
     */
    public function getProductCapacityLabel(): string
    {
        $productCapacityLabels = [
            self::TYPE_STATION => __('order.product_capacity_labels.station'),
            self::TYPE_TANKER => __('order.product_capacity_labels.tanker'),
            self::TYPE_DOMESTIC_STORAGE_TANK => __('order.product_capacity_labels.domestic_storage_tank'),
            self::TYPE_CENTRAL_STORAGE_TANK => __('order.product_capacity_labels.central_storage_tank'),
            self::TYPE_MAINTENANCE_STATION => __('order.product_capacity_labels.maintenance_station'),
            self::TYPE_MAINTENANCE_TANKER => __('order.product_capacity_labels.maintenance_tanker'),
            self::TYPE_MICRO_NETWORK => __('order.product_capacity_labels.micro_network'),
            self::TYPE_OTHER => __('order.product_capacity_labels.other'),
            self::TYPE_WELL_DRILLING => __('order.product_capacity_labels.well_drilling'),
            self::TYPE_RAINWATER_STORAGE => __('order.product_capacity_labels.rainwater_storage'),
            self::TYPE_HOME_FILTERS => __('order.product_capacity_labels.home_filters'),
            self::TYPE_WATER_BOTTLES => __('order.product_capacity_labels.water_bottles'),
            self::TYPE_COOLERS => __('order.product_capacity_labels.coolers'),
            self::TYPE_PRODUCTS_UNDER_REVIEW => __('order.product_capacity_labels.products_under_review'),
            self::TYPE_WELL_PURIFICATION_LICENSES => __('order.product_capacity_labels.well_purification_licenses'),
        ];

        return $productCapacityLabels[$this->type] ?? __('order_finance.capacity');
    }

    /**
     * Get available water sources
     */
    public static function getWaterSources(): array
    {
        return [
            self::WATER_SOURCE_GOVERNMENT => __('order.government'),
            self::WATER_SOURCE_PRIVATE => __('order.private'),
            self::WATER_SOURCE_CHARITY => __('order.charity'),
        ];
    }

    /**
     * Get available order statuses translations
     */
    public static function getOrderStatuses(): array
    {
        return [
            self::STATUS_CREATED => __('order.created'),
            self::STATUS_PENDING_RECOMMENDATION => __('order.pending_recommendation'),
            self::STATUS_RECOMMENDED => __('order.recommended'),
            self::STATUS_TECHNICAL_FINANCIAL_REQUESTED => __('order.technical_financial_requested'),
            self::STATUS_TECHNICAL_FINANCIAL_APPROVED => __('order.technical_financial_approved'),
            self::STATUS_PROJECT_MANAGER_APPROVED => __('order.project_manager_approved'),
            self::STATUS_CLASSIFICATION => __('order.classification'),
            self::STATUS_AGREEMENT => __('order.agreement'),
            self::STATUS_CEO_APPROVED => __('order.ceo_approved'),
            self::STATUS_LAUNCHED => __('order.launched'),
            self::STATUS_ACCEPTED => __('order.accepted'),
            self::STATUS_REJECTED => __('order.rejected'),
        ];
    }

    /**
     * Get the next status for approval workflow
     */
    public function getNextStatus(): ?string
    {
        $statusFlow = [
            self::STATUS_CREATED => self::STATUS_PENDING_RECOMMENDATION,
            self::STATUS_PENDING_RECOMMENDATION => self::STATUS_RECOMMENDED,
            self::STATUS_RECOMMENDED => self::STATUS_TECHNICAL_FINANCIAL_REQUESTED,
            self::STATUS_TECHNICAL_FINANCIAL_REQUESTED => self::STATUS_TECHNICAL_FINANCIAL_APPROVED,
            self::STATUS_TECHNICAL_FINANCIAL_APPROVED => self::STATUS_PROJECT_MANAGER_APPROVED,
            self::STATUS_PROJECT_MANAGER_APPROVED => self::STATUS_CLASSIFICATION,
            self::STATUS_CLASSIFICATION => self::STATUS_AGREEMENT,
            self::STATUS_AGREEMENT => self::STATUS_CEO_APPROVED,
            self::STATUS_CEO_APPROVED => self::STATUS_LAUNCHED,
            self::STATUS_LAUNCHED => self::STATUS_ACCEPTED,
            self::STATUS_ACCEPTED => null,
            self::STATUS_REJECTED => null,
        ];

        return $statusFlow[$this->status] ?? null;
    }

    /**
     * Get the previous status for sending back workflow
     */
    public function getPreviousStatus(): ?string
    {
        $statusFlow = [
            self::STATUS_CREATED => null,
            self::STATUS_PENDING_RECOMMENDATION => null,
            self::STATUS_RECOMMENDED => self::STATUS_PENDING_RECOMMENDATION,
            self::STATUS_TECHNICAL_FINANCIAL_REQUESTED => self::STATUS_RECOMMENDED,
            self::STATUS_TECHNICAL_FINANCIAL_APPROVED => self::STATUS_TECHNICAL_FINANCIAL_REQUESTED,
            self::STATUS_PROJECT_MANAGER_APPROVED => self::STATUS_TECHNICAL_FINANCIAL_APPROVED,
            self::STATUS_CLASSIFICATION => self::STATUS_PROJECT_MANAGER_APPROVED,
            self::STATUS_AGREEMENT => self::STATUS_CLASSIFICATION,
            self::STATUS_CEO_APPROVED => self::STATUS_AGREEMENT,
            self::STATUS_LAUNCHED => self::STATUS_CEO_APPROVED,
            self::STATUS_ACCEPTED => self::STATUS_LAUNCHED,
            self::STATUS_REJECTED => null,
        ];

        return $statusFlow[$this->status] ?? null;
    }

    /**
     * Check if order can be sent back to previous stage
     */
    public function canSendBackToPreviousStage(): bool
    {
        // Check if we have a previous status
        return $this->getPreviousStatus() !== null;
    }

    /**
     * Send order back to previous stage and cleanup related records
     */
    public function sendBackToPreviousStage(string $notes = ''): bool
    {
        $previousStatus = $this->getPreviousStatus();
        if (! $previousStatus) {
            return false;
        }

        $currentStatus = $this->status;
        $oldStatus = $this->status;

        // Cleanup records created during current stage
        $this->cleanupRecordsForStatus($currentStatus);

        // Update status
        $this->status = $previousStatus;
        $this->save();

        // Log the send back activity
        activity()
            ->performedOn($this)
            ->causedBy(Auth::user())
            ->event('send_back')
            ->withProperties([
                'old_status' => $oldStatus,
                'new_status' => $previousStatus,
                'notes' => $notes,
                'action' => 'sent_back',
            ])
            ->log("Order sent back from {$oldStatus} to {$previousStatus}");

        return true;
    }

    /**
     * Cleanup records created during a specific status stage
     */
    protected function cleanupRecordsForStatus(string $status): void
    {
        switch ($status) {
            case self::STATUS_PROJECT_MANAGER_APPROVED:
                // When sending back from PROJECT_MANAGER_APPROVED, delete finance record
                if ($this->finance) {
                    $this->finance->delete();
                }
                break;

            case self::STATUS_AGREEMENT:
                // When sending back from AGREEMENT, delete agreement record and files
                if ($this->agreement) {
                    // Delete associated agreement file from media library
                    $this->getFirstMedia('agreement_file')?->delete();
                    $this->agreement->delete();
                }
                break;

            case self::STATUS_CEO_APPROVED:
                // When sending back from CEO_APPROVED, delete any project charter if it exists
                if ($this->projectCharter) {
                    $this->projectCharter->delete();
                }
                // Also delete order agreement requirement
                $this->requirements()
                    ->where('name', OrderRequirement::ORDER_AGREEMENT_REQUIREMENT)
                    ->delete();
                break;

            case self::STATUS_TECHNICAL_FINANCIAL_REQUESTED:
                // When sending back from TECHNICAL_FINANCIAL_REQUESTED, delete auto-created requirements
                $this->requirements()
                    ->whereIn('name', OrderRequirement::TECHNICAL_FINANCIAL_REQUIREMENTS)
                    ->delete();
                break;

            case self::STATUS_CLASSIFICATION:
                // When sending back from CLASSIFICATION, detach all donor financial portfolio allocations
                $this->donorFinancialPortfolios()->detach();
                break;

            default:
                // No specific cleanup needed for other statuses
                break;
        }

        // Log the cleanup activity
        activity()
            ->performedOn($this)
            ->causedBy(Auth::user())
            ->withProperties([
                'status' => $status,
                'action' => 'cleanup_records',
            ])
            ->log("Cleaned up records for status {$status}");
    }

    public function isTherePendingRequirements(): bool
    {
        // all order requirements must be accepted or rejected
        if ($this->requirements->contains(fn ($req) => in_array($req->status, [OrderRequirement::STATUS_PENDING, OrderRequirement::STATUS_ASK_MODIFICATION]))) {
            return true;
        }

        return false;
    }

    /**
     * Check if all required finance fields are filled
     */
    public function hasCompleteFinanceData(): bool
    {
        if (! $this->finance) {
            return false;
        }

        $requiredFields = [
            'count',
            'capacity',
            'execution_duration',
            'company_name',
            'offer_price',
            'additional_fees',
            'operation_cost_percentage',
        ];

        foreach ($requiredFields as $field) {
            if (empty($this->finance->$field)) {
                return false;
            }
        }

        return true;
    }

    /**
     * Get validation errors for finance data
     */
    public function getFinanceValidationErrors(): array
    {
        $errors = [];

        if (! $this->finance) {
            $errors[] = __('order.finance_not_created');

            return $errors;
        }

        $requiredFields = [
            'order_requirement_id' => __('order_finance.order_requirement_id'),
            'count' => __('order_finance.count'),
            'capacity' => __('order_finance.capacity'),
            'execution_duration' => __('order_finance.execution_duration'),
            'company_name' => __('order_finance.company_name'),
            'offer_price' => __('order_finance.offer_price'),
            'additional_fees' => __('order_finance.additional_fees'),
            // 'operation_cost_percentage' => __('order_finance.operation_cost_percentage'),
        ];

        foreach ($requiredFields as $field => $label) {
            if (empty($this->finance->$field)) {
                $errors[] = __('order.field_required', ['field' => $label]);
            }
        }

        return $errors;
    }

    /**
     * Get a formatted validation message for incomplete finance data
     */
    public function getFinanceValidationMessage(): string
    {
        $errors = $this->getFinanceValidationErrors();

        if (empty($errors)) {
            return '';
        }

        return __('order.cannot_approve_incomplete_finance')."\n".implode("\n", $errors);
    }

    /**
     * Check if order can be approved to next stage
     */
    public function canApproveToNextStage(): bool
    {
        // Check if we have a next status
        if ($this->getNextStatus() === null) {
            return false;
        }

        // For TECHNICAL_FINANCIAL_APPROVED status, we don't check finance data here
        // because it will be collected in the approval modal
        return true;
    }

    /**
     * Approve order to next stage
     */
    public function approveToNextStage(string $notes = ''): bool
    {
        $nextStatus = $this->getNextStatus();
        if (! $nextStatus) {
            return false;
        }

        // Check if we can approve to next stage (includes finance validation)
        if (! $this->canApproveToNextStage()) {
            return false;
        }

        $oldStatus = $this->status;
        $this->status = $nextStatus;
        $this->save();

        // Log the approval activity
        activity()
            ->performedOn($this)
            ->causedBy(Auth::user())
            ->event('approved')
            ->withProperties([
                'old_status' => $oldStatus,
                'new_status' => $nextStatus,
                'action' => 'approved',
                'notes' => $notes,
            ])
            ->log('Order approved to next stage');

        // If moving to TECHNICAL_FINANCIAL_REQUESTED, create default requirements
        if ($nextStatus === self::STATUS_TECHNICAL_FINANCIAL_REQUESTED) {
            $this->createTechnicalFinancialRequirements();
        } elseif ($nextStatus === self::STATUS_CEO_APPROVED) {
            // If moving to AGREEMENT, create order agreement requirement
            $this->createOrderAgreementRequirement();
        }

        return true;
    }

    /**
     * Create technical and financial requirements automatically
     */
    protected function createTechnicalFinancialRequirements(): void
    {
        $requirements = OrderRequirement::TECHNICAL_FINANCIAL_REQUIREMENTS;

        foreach ($requirements as $requirementName) {
            // Check if requirement already exists to avoid duplicates
            $existingRequirement = $this->requirements()
                ->where('name', $requirementName)
                ->first();

            if (! $existingRequirement) {
                $this->requirements()->create([
                    'name' => $requirementName,
                    'status' => OrderRequirement::STATUS_PENDING,
                ]);
            }
        }

        // Log the automatic creation
        activity()
            ->performedOn($this)
            ->causedBy(Auth::user())
            ->event('requirements_auto_created')
            ->withProperties([
                'requirements_created' => $requirements,
                'status' => $this->status,
            ])
            ->log('Technical and financial requirements automatically created');
    }

    /**
     * create order agreement requirement automatically
     */
    protected function createOrderAgreementRequirement(): void
    {
        $requirement = OrderRequirement::ORDER_AGREEMENT_REQUIREMENT;

        // check if requirement already exists to avoid duplicates
        $existingRequirement = $this->requirements()
            ->where('name', $requirement)
            ->first();

        if (! $existingRequirement) {
            $this->requirements()->create([
                'name' => $requirement,
                'status' => OrderRequirement::STATUS_PENDING,
            ]);
        }

        activity()
            ->performedOn($this)
            ->causedBy(Auth::user())
            ->event('agreement_requirement_auto_created')
            ->withProperties([
                'requirement_created' => $requirement,
                'status' => $this->status,
            ])
            ->log('Order agreement requirement automatically created');
    }

    /**
     * Reject order and deallocate all portfolio funding
     */
    public function reject(string $notes = ''): void
    {
        $oldStatus = $this->status;
        $this->status = self::STATUS_REJECTED;

        // Deallocate all funding from donor portfolios when rejecting the order
        $allocatedPortfolios = $this->donorFinancialPortfolios()->get();

        if ($allocatedPortfolios->isNotEmpty()) {
            // Log the deallocation for audit purposes
            foreach ($allocatedPortfolios as $portfolio) {
                $allocatedAmount = $portfolio->pivot->allocated_amount;
                activity()
                    ->performedOn($this)
                    ->causedBy(Auth::user())
                    ->event('portfolio_deallocated')
                    ->withProperties([
                        'portfolio_id' => $portfolio->id,
                        'portfolio_name' => $portfolio->name,
                        'deallocated_amount' => $allocatedAmount,
                        'reason' => 'order_rejected',
                    ])
                    ->log('Portfolio funding deallocated due to order rejection');
            }

            // Remove all portfolio allocations
            $this->donorFinancialPortfolios()->detach();
        }

        $this->save();

        // Log the rejection activity
        activity()
            ->performedOn($this)
            ->causedBy(Auth::user())
            ->event('rejected')
            ->withProperties([
                'old_status' => $oldStatus,
                'new_status' => self::STATUS_REJECTED,
                'action' => 'rejected',
                'notes' => $notes,
                'deallocated_portfolios_count' => $allocatedPortfolios->count(),
            ])
            ->log('Order rejected and portfolio funding deallocated');
    }

    /**
     * Register media collections
     */
    public function registerMediaCollections(): void
    {
        $this->addMediaCollection('order_files')
            ->acceptsMimeTypes([
                'application/pdf',
                'image/jpeg',
                'image/png',
                'image/jpg',
            ]);

        $this->addMediaCollection('agreement_file')
            // ->singleFile()
            ->acceptsMimeTypes([
                'application/pdf',
                'image/jpeg',
                'image/png',
                'image/jpg',
            ]);
    }

    /**
     * Add media with custom properties
     */
    public function addOrderFile($file, string $title, string $placeholder = ''): Media
    {
        return $this->addMedia($file)
            ->withCustomProperties([
                'title' => $title,
                'placeholder' => $placeholder,
            ])
            ->toMediaCollection('order_files');
    }

    /**
     * Get all order files, keeping only the last file when there are duplicates with the same file_title
     */
    public function getOrderFiles()
    {
        $allFiles = $this->getMedia('order_files');

        // Group files by file_title custom property
        $groupedByTitle = $allFiles->groupBy(function ($media) {
            return $media->getCustomProperty('title') ?? $media->getCustomProperty('file_title');
        });

        // Keep only the last (most recent) file for each title
        return $groupedByTitle->map(function ($files) {
            return $files->sortByDesc('created_at')->first();
        })->values();
    }

    public function getAgreementFile(): ?Media
    {
        return $this->getFirstMedia('agreement_file');
    }

    /**
     * Get the agreement file temporary URL for download
     */
    public function getAgreementFileUrl(): ?string
    {
        $media = $this->getAgreementFile();

        return $media ? $media->getTemporaryUrl(Carbon::now()->addMinutes(5)) : null;
    }

    /**
     * Calculate total families from selected centers
     */
    public function calculateTotalFamilies(): int
    {
        return $this->residentialGatherings()->sum('families_count');
    }

    public function getActivitylogOptions(): LogOptions
    {
        return LogOptions::defaults()
            ->useLogName('order');
    }

    /**
     * Returns the 'lat' and 'lng' attributes as the computed 'location' attribute,
     * as a standard Google Maps style Point array with 'lat' and 'lng' attributes.
     *
     * Used by the Filament Google Maps package.
     *
     * Requires the 'location' attribute be included in this model's $fillable array.
     */
    public function getLocationAttribute(): array
    {
        return [
            'lat' => (float) $this->lat,
            'lng' => (float) $this->lng,
        ];
    }

    /**
     * Takes a Google style Point array of 'lat' and 'lng' values and assigns them to the
     * 'lat' and 'lng' attributes on this model.
     *
     * Used by the Filament Google Maps package.
     *
     * Requires the 'location' attribute be included in this model's $fillable array.
     */
    public function setLocationAttribute(?array $location): void
    {
        if (is_array($location)) {
            $this->attributes['lat'] = $location['lat'];
            $this->attributes['lng'] = $location['lng'];
            unset($this->attributes['location']);
        }
    }

    /**
     * Get the lat and lng attribute/field names used on this table
     *
     * Used by the Filament Google Maps package.
     *
     * @return string[]
     */
    public static function getLatLngAttributes(): array
    {
        return [
            'lat' => 'lat',
            'lng' => 'lng',
        ];
    }

    /**
     * Get the name of the computed location attribute
     *
     * Used by the Filament Google Maps package.
     */
    public static function getComputedLocation(): string
    {
        return 'location';
    }

    public function getActivityForStatus($status): ?Activity
    {
        return $this->activities()
            ->where('properties->old_status', $status)
            ->where('event', 'approved')
            ->latest()
            ->first();
    }

    /**
     * takes an order status and checks the activity log to see if it is approved
     *
     * Used by the Filament Google Maps package.
     */
    public function isStatusCompleted($status): bool
    {
        $activity = $this->getActivityForStatus($status);

        Log::debug('Checking if order status is completed', [
            'order_id' => $this->id,
            'status' => $status,
            'activity' => $activity,
        ]);

        return $activity !== null;
    }

    /**
     * Scope to filter orders by user's order type permissions
     */
    public function scopeFilterByTypePermissions($query, $user = null)
    {
        $user = $user ?? Auth::user();

        // If no user is authenticated, show no results
        if (! $user) {
            return $query->whereRaw('1 = 0');
        }

        // If user has permission to view all order types, don't filter
        if ($user->can('view_all_order_types_order')) {
            return $query;
        }

        // Get all order types and their corresponding permissions
        $orderTypePermissions = $this->getOrderTypePermissions();

        // Check which order types the user can view
        $allowedTypes = [];
        foreach ($orderTypePermissions as $orderType => $permission) {
            if ($user->can($permission)) {
                $allowedTypes[] = $orderType;
            }
        }

        // If user has no specific order type permissions, show no results
        if (empty($allowedTypes)) {
            return $query->whereRaw('1 = 0');
        }

        // Filter by allowed order types
        return $query->whereIn('type', $allowedTypes);
    }

    /**
     * Get the order type permissions mapping
     */
    public static function getOrderTypePermissions(): array
    {
        return [
            self::TYPE_STATION => 'view_station_order_type_order',
            self::TYPE_TANKER => 'view_tanker_order_type_order',
            self::TYPE_DOMESTIC_STORAGE_TANK => 'view_domestic_storage_tank_order_type_order',
            self::TYPE_CENTRAL_STORAGE_TANK => 'view_central_storage_tank_order_type_order',
            self::TYPE_MAINTENANCE_STATION => 'view_maintenance_station_order_type_order',
            self::TYPE_MAINTENANCE_TANKER => 'view_maintenance_tanker_order_type_order',
            self::TYPE_MICRO_NETWORK => 'view_micro_network_order_type_order',
            self::TYPE_OTHER => 'view_other_order_type_order',
            self::TYPE_WELL_DRILLING => 'view_well_drilling_order_type_order',
            self::TYPE_RAINWATER_STORAGE => 'view_rainwater_storage_order_type_order',
            self::TYPE_HOME_FILTERS => 'view_home_filters_order_type_order',
            self::TYPE_WATER_BOTTLES => 'view_water_bottles_order_type_order',
            self::TYPE_COOLERS => 'view_coolers_order_type_order',
            self::TYPE_PRODUCTS_UNDER_REVIEW => 'view_products_under_review_order_type_order',
            self::TYPE_WELL_PURIFICATION_LICENSES => 'view_well_purification_licenses_order_type_order',
        ];
    }

    /**
     * get current status notes from activity log
     */
    public function getCurrentStatusNotesAttribute(): ?string
    {
        $activity = $this->activities()
            // where event is send_back, approved, or rejected
            ->whereIn('event', ['send_back', 'approved', 'rejected'])
            // where properties->new_status is equal to current status
            ->where('properties->new_status', $this->status)
            ->orderBy('created_at', 'desc')
            ->first();

        return $activity?->properties['notes'] ?? null;
    }
}
