<?php

namespace App\Models;

use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use Illuminate\Support\Facades\DB;
use Carbon\Carbon;
use App\Scopes\ZoneScope;

class DeliveryMan extends Authenticatable
{
    use Notifiable;

    protected $casts = [
        'zone_id' => 'integer',
        'status'=>'boolean',
        'active'=>'integer',
        'available'=>'integer',
        'earning'=>'float',
        'store_id'=>'integer',
        'current_orders'=>'integer',
        'vehicle_id'=>'integer',
    ];

    public function getFullNameAttribute(): string
    {
        return trim($this->f_name . ' ' . $this->l_name);
    }

    protected $hidden = [
        'password',
        'auth_token',
    ];

    public function blockingLogs(): \Illuminate\Database\Eloquent\Relations\HasMany
    {
        return $this->hasMany(DeliveryManBlockingLog::class, 'delivery_man_id')->orderBy('id', 'ASC');
    }
    public function monthlySubscriptions(): \Illuminate\Database\Eloquent\Relations\HasMany
    {
        return $this->hasMany(DMMonthlySubscription::class, 'delivery_man_id')->orderBy('id', 'ASC');
    }

    public function userinfo(): \Illuminate\Database\Eloquent\Relations\HasOne
    {
        return $this->hasOne(UserInfo::class,'deliveryman_id', 'id');
    }

    public function vehicle()
    {
        return $this->belongsTo(DMVehicle::class);
    }

    public function wallet()
    {
        return $this->hasOne(DeliveryManWallet::class);
    }

    public function orders()
    {
        return $this->hasMany(Order::class);
    }

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

    public function todays_earning()
    {
        return $this->hasMany(OrderTransaction::class)->whereDate('created_at',now());
    }

    public function this_week_earning()
    {
        return $this->hasMany(OrderTransaction::class)->whereBetween('created_at', [Carbon::now()->startOfWeek(), Carbon::now()->endOfWeek()]);
    }

    public function this_month_earning()
    {
        return $this->hasMany(OrderTransaction::class)->whereMonth('created_at', date('m'))->whereYear('created_at', date('Y'));
    }

    public function todaysorders()
    {
        return $this->hasMany(Order::class)->whereDate('accepted',now());
    }

    public function total_delivered_orders()
    {
        return $this->hasMany(Order::class)->where('order_status','delivered');
    }

    public function this_week_orders()
    {
        return $this->hasMany(Order::class)->whereBetween('accepted', [Carbon::now()->startOfWeek(), Carbon::now()->endOfWeek()]);
    }

    public function delivery_history()
    {
        return $this->hasMany(DeliveryHistory::class, 'delivery_man_id');
    }

    public function last_location()
    {
        return $this->hasOne(DeliveryHistory::class, 'delivery_man_id')->latest();
    }

    public function zone()
    {
        return $this->belongsTo(Zone::class);
    }

    public function reviews()
    {
        return $this->hasMany(DMReview::class);
    }

    public function rating()
    {
        return $this->hasMany(DMReview::class)
            ->select(DB::raw('avg(rating) average, count(delivery_man_id) rating_count, delivery_man_id'))
            ->groupBy('delivery_man_id');
    }

    public function scopeActive($query)
    {
        return $query->where('active', 1)->where('application_status','approved');
    }
    public function scopeInActive($query)
    {
        return $query->where('active', 0)->where('application_status','approved');
    }

    public function scopeEarning($query)
    {
        return $query->where('earning', 1);
    }

    public function scopeAvailable($query)
    {
        return $query->where('current_orders', '<' ,config('dm_maximum_orders')??1);
    }

    public function scopeUnavailable($query)
    {
        return $query->where('current_orders', '>' ,config('dm_maximum_orders')??1);
    }

    public function scopeZonewise($query)
    {
        return $query->where('type','zone_wise');
    }

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

    public function orderTransactions ($fromDate = '', $toDate = '')
    {
        $result = $this->hasMany(OrderTransaction::class);
        if(!empty($fromDate) and !empty($toDate)){
            $result = $result->where('created_at', '>=', $fromDate)->where('created_at', '<=', $toDate);
        }
        return $result;
    }

    public function orderTransactionsOnlyForVendors ($fromDate = '', $toDate = '')
    {
        $result = $this->hasMany(OrderTransaction::class)->whereNotNull('vendor_id');
        if(!empty($fromDate) and !empty($toDate)){
            $result = $result->where('created_at', '>=', $fromDate)->where('created_at', '<=', $toDate);
        }
        return $result;
    }

    public static function getTotalCollectedFromDeliveryMan($dm, $fromDate = '', $toDate = '')
    {
        $result = AccountTransaction::where('from_type', 'deliveryman')->where('from_id', $dm->id);
        if(!empty($fromDate) and !empty($toDate)){
            $result = $result->where('created_at', '>=', $fromDate)->where('created_at', '<=', $toDate);
        }
        return $result->sum('amount');
    }

    public static function getTotalEarning($dm, $fromDate = '', $toDate = '')
    {
        return (int) $dm->orderTransactions($fromDate, $toDate)->sum('original_delivery_charge');
    }

    public static function getCommissionFromDeliveryMan($dm, $fromDate = '', $toDate = '')
    {
        $totalEarning = $dm->orderTransactions($fromDate, $toDate)->sum('delivery_charge');
        return $totalEarning - DeliveryMan::getTotalEarning($dm, $fromDate, $toDate);
    }

    public static function getCountOfOrders($dm, $fromDate = '', $toDate = '')
    {
        return $dm->orderTransactions($fromDate, $toDate)->count();
    }

    public static function getCommissionFromStore($dm, $fromDate = '', $toDate = '')
    {
        return $dm->orderTransactionsOnlyForVendors($fromDate, $toDate)->sum('commission_amount_from_store');//$dm->orderTransactionsOnlyForVendors($fromDate, $toDate)->sum('order_amount') - $dm->orderTransactionsOnlyForVendors($fromDate, $toDate)->sum('store_amount'); // - $dm->orderTransactionsOnlyForVendors($fromDate, $toDate)->sum('delivery_charge')
    }

    public static function getTheRemainingBalanceForDeliveryMan($dm, $fromDate = '', $toDate = '')
    {
        return (DeliveryMan::getCommissionFromDeliveryMan($dm, $fromDate, $toDate) + DeliveryMan::getCommissionFromStore($dm, $fromDate, $toDate)) - DeliveryMan::getTotalCollectedFromDeliveryMan($dm, $fromDate, $toDate);
    }

    public static function getDeliveryManReviews($ID): array
    {

        $DM = DeliveryMan::where('id', $ID)->first();

        $count = $DM->reviews->count();
        $sum = $DM->reviews->sum('rating');
        $avg = $count > 0 ? $sum / $count : 0;
        if($avg == 0){
            $avg = 0.1;
        }
        if(is_int($avg)){
            $avg = (double)($avg . '.1');
        }
        return [
            'delivery_man_id' => $ID,
            'count' => $count,
            'avg' => $avg,
        ];
    }

    public function bonuses(): \Illuminate\Database\Eloquent\Relations\HasMany
    {
        return $this->hasMany(DMBouns::class, 'delivery_man_id');
    }

    public static function getCurrentOrdersCount($dm)
    {
        return Order::where('delivery_man_id', $dm->id)->whereNotIn('order_status', ['delivered', 'canceled'])->count();
    }

    public static function isHaveActiveMonthlySubscription($deliveryManId)
    {
        $currentTime = Carbon::now();
        return DMMonthlySubscription::where('delivery_man_id', $deliveryManId)
            ->where('start_at', '<=', $currentTime)
            ->where('end_at', '>=', $currentTime)
            ->exists();
    }
}
