<?php

namespace App\Models\OrderManagement;

use App\Models\LocalizationManagement\Address;
use App\Models\OrderManagement\Scopes\OrderGlobalScope;
use App\Models\PaymentManagement\PaymentMethod;
use App\Models\PaymentManagement\Traits\HasPaymentsUsages;
use App\Models\ProductManagement\Product;
use App\Models\SettingManagement\Status;
use App\Models\SettingManagement\Traits\Statuable;
use App\Models\StockManagement\Warehouse;
use App\Models\Traits\Bootables\Auditable;
use App\Models\UserManagement\Admin;
use App\Models\UserManagement\Customer;
use App\Notifications\Backend\User\OrderCreatedNotification;
use App\Notifications\Frontend\User\OrderThanksNotification;
use Axn\EloquentAuthorable\AuthorableTrait;
use Database\Factories\OrderFactory;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
use Illuminate\Support\Facades\File;
use Mccarlosen\LaravelMpdf\Facades\LaravelMpdf as PDF;
use Mpdf\MpdfException;
use Nicolaslopezj\Searchable\SearchableTrait;

class Order extends Model{
    use HasFactory, SearchableTrait,SoftDeletes,
        HasPaymentsUsages,Statuable,AuthorableTrait,Auditable;

//    public $authorable = [
//        'users_model' => \App\Admin::class,
//        'guard' => 'admin',
//        'created_by_column_name' => 'custom_created_by',
//        'updated_by_column_name' => 'custom_updated_by',
//        'set_author_when_creating' => false,
//        'set_author_when_updating' => false,
//    ];

    protected $table = "order_mgt__orders";

    protected $guarded = ["id"];

    protected $appends = [
        "editable",
        "reason",
    ];

    protected static function booted(){
        static::addGlobalScope(new OrderGlobalScope);
    }

    protected static function newFactory(){
        return OrderFactory::new();
    }


    public static function getStatuses(){
       $statuses =  [
            Status::UNPROCESSED,
            Status::PAID,
            Status::UNDER_PROCESS,
            Status::DELIVERED,
            Status::REFUNDED_REQUEST,
            Status::RETURNED_ORDER,
            Status::REFUNDED_ORDER,
            Status::CANCELED,
            Status::REJECTED,
            Status::COMPLETED,
        ];

       return Status::whereIn("code",$statuses)->get();
    }

    public static function getStatusesNotModifiables(){
        return [
            Status::DELIVERED,
            Status::CANCELED,
            Status::REFUNDED_ORDER,
            Status::COMPLETED,
        ];
    }


    public static function getStatusesRequiredRaesons(){
        return [
            Status::CANCELED,
            Status::REFUNDED_REQUEST,
            Status::REJECTED,
        ];
    }

    public static function getStatusesCollected(){
        return [
            Status::PAID,
            Status::DELIVERED,
            Status::UNDER_PROCESS,
            Status::COMPLETED,
        ];
    }

    public static function getStatusesRollbackStock(){
        return [
            Status::CANCELED,
            Status::REJECTED,
            Status::REFUNDED_ORDER,
            Status::RETURNED_ORDER,
        ];
    }

    /**
     * @throws MpdfException
     */
    public function generateInvoice(){
        $order = $this;
        // Send email with PDF invoice
        $pdf = PDF::loadView('layouts.invoice', compact("order"));
        $saved_file = public_path("$order->ref_id.pdf");
        $pdf->save($saved_file);

        try {
            // Notification to admins.
            Admin::active()->get()->map->notify(new OrderCreatedNotification($order));

            $customer = $order->customer;
            //Notication client
            $customer->notify(new OrderThanksNotification($order, $saved_file));
        }catch (\Exception $exception){

        } finally {
            File::delete($saved_file);
        }
    }

    public static function newId($created_at = null,$period = null){
        $created_at = (blank($created_at)) ? now() : $created_at;
        $period = blank($period) ? getSettingsOf("current_orders_period") : $period;

        $period = blank($period) ? format_date($created_at,'Y-m') : $period;

       // dd($period);

//        $prefix = "ORD";
        $prefix = "";
        $optionsId = [
            "prefix" => $prefix.format_date($period,'ym'),
            "count_by" => [
                "column" => "period",
                "keyName" => "ref_id",
                "value" => $period,
            ]
        ];
        $total_orders_per_period = strlen((string) 9999);
       // dd(newId(Order::class,$total_orders_per_period,$optionsId));
        return newId(Order::class,$total_orders_per_period,$optionsId); // "22010001"
    }


    //RELATIONS
    public function user(){
        return $this->belongsTo(Admin::class,"created_by");
    }

    public function customer(){
        return $this->belongsTo(Customer::class,"customer_id");
    }

    public function userAddress(){
        return $this->belongsTo(Address::class,"address_id");
    }

    public function products() {
        return $this->belongsToMany(
            Product::class,
            (new OrderProduct)->getTable(),
            "order_id",
            "product_id"
        )
       ->withPivot('quantity','price',"amount");
    }

    public function transactions(){
        return $this->hasMany(OrderTransaction::class);
    }

    public function items(){
        return $this->hasMany(OrderProduct::class,"order_id");
    }
    public function paymentMethod(){
        return $this->belongsTo(PaymentMethod::class,"payment_method_id");
    }

    public function shippingCompany(){
        return $this->belongsTo(ShippingCompany::class,"shipping_company_id");
    }

    public function warehouse(){
        return $this->belongsTo(Warehouse::class,"warehouse_id");
    }
//
    public function pointOfSale(){
        return $this->belongsTo(Warehouse::class,"point_of_sale_id");
    }

    public function billingDesk(){
        return $this->belongsTo(BillingDesk::class,"billing_desk_id");
    }

    //ACTIONS
    public function currency(){
        switch ($this->currency) {
            case 'USD': return 'XAF';
            case 'SAR': return 'SR';
            case 'CFA': return 'XAF';
            default: return $this->currency;
        }
    }


    public function statusWithBadge(){
        return $this->status->badge_label ?? "---";
    }

    public function getNextStatuses(){
        return self::getStatuses()->where("code","<>" ,$this->status_code);
    }

    public function getEditableAttribute(){
        return !in_array($this->status_code,Order::getStatusesNotModifiables());
    }


    public function getReasonAttribute(){
        $status_change = $this->statusChanges()
                            ->where("status_code" , $this->status_code)
                            ->whereNotNull("message")
                            ->first();

        if($status_change){
            return $status_change->message;
        }

        return null;
    }

    ///GETTERS
//    public function getWarehouseAttribute(){
//        return $this->userAddress->warehouse ?? null;
//    }
}
