<?php

namespace App\Models;

use App\Enums\BudgetType;
use App\Enums\BudgetStatusType;
use App\Models\Traits\Filterable;
use App\Models\Traits\SelectOptions;
use App\Models\Traits\FilterDepartment;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Factories\HasFactory;

class Budget extends Model
{
  use HasFactory, Filterable, SelectOptions, FilterDepartment;

  protected $fillable = [
    'company_id',
    'user_id',
    'balance_id',
    'department_id',
    'name',
    'code',
    'type',
    'date',
    'year',
    'debit_amount',
    'credit_amount',
    'description',
    'status',
    'status_message',
    'review_at',
  ];

  protected $casts = [
    'type' => BudgetType::class,
    'status' => BudgetStatusType::class,
    'review_at' => 'datetime',
  ];

  protected $appends = ['remaining_amount', 'paid_remaining_amount'];
  public function getRemainingAmountAttribute()
  {
    $debit_amount = intval($this->debit_amount);
    $credit_amount = intval($this->credit_amount);
    return $debit_amount - $credit_amount;
  }

  public function getPaidRemainingAmountAttribute()
  {
    if (!isset($this->paid_amount))
      return null;
    $debit_amount = intval($this->debit_amount);
    $credit_amount = intval($this->credit_amount);
    $paid_amount = intval($this->paid_amount);
    $pending_payment_amount = isset($this->pending_payment_amount) ? intval($this->pending_payment_amount) : 0;

    return $debit_amount - $credit_amount - $paid_amount - $pending_payment_amount;
  }

  public function company()
  {
    return $this->belongsTo(Company::class, 'company_id');
  }

  public function user()
  {
    return $this->belongsTo(User::class, 'user_id');
  }
  public function reviewer()
  {
    return $this->belongsTo(User::class, 'user_review_id');
  }

  public function balance()
  {
    return $this->belongsTo(Balance::class, 'balance_id');
  }

  public function department()
  {
    return $this->belongsTo(Department::class, 'department_id');
  }

  public function details()
  {
    return $this->hasMany(BudgetDetail::class, 'budget_id');
  }

  public function budgetDetails()
  {
    return $this->hasMany(BudgetDetail::class, 'budget_id');
  }

  public function budgetCategories()
  {
    return $this->hasMany(BudgetCategory::class);
  }

  public function transactions()
  {
    return $this->hasManyThrough(Transaction::class, BudgetDetail::class, 'budget_id', 'budget_detail_id');
  }

  public function payments()
  {
    return $this->hasMany(Payment::class, 'budget_id');
  }

  public function approvalLogs()
  {
    return $this->hasMany(ApprovalLog::class, 'budget_id');
  }

  public function notifications()
  {
    return $this->hasMany(Notification::class, 'budget_id');
  }

  public function latestApprovalLog()
  {
    return $this->hasOne(ApprovalLog::class, 'budget_id')->latestOfMany();
  }

  public function scopeWithUserAction($query)
  {
    return $query->addSelect([
      'approval_level' => \App\Models\ApprovalLog::select('approval_level')
        ->whereColumn('budget_id', 'budgets.id')
        ->whereIn('action', [\App\Enums\ActionStatusType::Submit, \App\Enums\ActionStatusType::Revise])
        ->orderBy('id', 'desc')
        ->limit(1),
    ]);
  }

  public function scopeWithPaidAmount($query)
  {
    return $query->addSelect([
      'paid_amount' => Payment::selectRaw('coalesce(sum(amount), 0)')
        ->whereColumn('budget_id', 'budgets.id')
        ->where('status', \App\Enums\PaymentStatusType::Paid),
      'paid_percentage' => Payment::selectRaw('case when (budgets.debit_amount - budgets.credit_amount) = 0 then 0 else (coalesce(sum(amount), 0) / (budgets.debit_amount - budgets.credit_amount)) * 100 end')
        ->whereColumn('budget_id', 'budgets.id')
        ->where('status', \App\Enums\PaymentStatusType::Paid),
    ]);
  }
  public function scopeWithPendingPayment($query)
  {
    return $query->addSelect([
      'pending_payment_amount' => Payment::selectRaw('coalesce(sum(amount), 0)')
        ->whereColumn('budget_id', 'budgets.id')
        ->where('status', \App\Enums\PaymentStatusType::Pending),
    ]);
  }
}
