<?php

namespace App\Models;

use App\Enums\ModuleType;
use App\Enums\ActionStatusType;
use App\Enums\UserDepartmentType;
use App\Models\Traits\Filterable;
use App\Models\Traits\SelectOptions;
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Factories\HasFactory;

class ApprovalLog extends Model
{
  use HasFactory, Filterable, SelectOptions;

  protected $fillable = [
    'user_id',
    'department_id',
    'approval_department_id',
    'budget_id',
    'budget_detail_id',
    'payment_id',
    'module_type',
    'action',
    'submit_level',
    'approval_level',
    'is_finance',
    'note',

    'ip_address',
    'user_agent',
    'detail',
    'parent_id',
  ];

  protected $casts = [
    'module_type' => ModuleType::class,
    'action' => ActionStatusType::class,
    'submit_level' => UserDepartmentType::class,
    'approval_level' => UserDepartmentType::class,
    'is_finance' => 'boolean',
  ];

  // protected $hidden = ['user_agent', 'detail'];
  protected static ?array $defaultSelectCols = null;

  protected static function booted(): void
  {
    static::addGlobalScope('default_cols', function (Builder $builder) {
      if (!is_null($builder->getQuery()->columns)) {
        return;
      }

      $instance = new static;

      if (static::$defaultSelectCols === null) {
        $table = $instance->getTable();

        static::$defaultSelectCols = array_values(array_diff(
          Schema::getColumnListing($table),
          ['user_agent', 'detail']
        ));
      }

      $builder->select(static::$defaultSelectCols);
    });
  }

  protected function applyDefaultSelect(Builder $builder): Builder
  {
    if (is_null($builder->getQuery()->columns)) {
      if (static::$defaultSelectCols === null) {
        $table = $this->getTable();

        static::$defaultSelectCols = array_values(array_diff(
          Schema::getColumnListing($table),
          ['user_agent', 'detail']
        ));
      }

      $builder->select(static::$defaultSelectCols);
    }

    return $builder;
  }

  public function scopeWithDetail(Builder $query): Builder
  {
    $this->applyDefaultSelect($query);
    return $query->addSelect($this->getTable() . '.detail');
  }

  public function scopeWithUserAgent(Builder $query): Builder
  {
    $this->applyDefaultSelect($query);
    return $query->addSelect($this->getTable() . '.user_agent');
  }

  public function scopeWithSelectAll(Builder $query): Builder
  {
    $this->applyDefaultSelect($query);
    return $query->addSelect([
      $this->getTable() . '.detail',
      $this->getTable() . '.user_agent',
    ]);
  }

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

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

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

  public function budget()
  {
    return $this->belongsTo(Budget::class, 'budget_id');
  }

  public function budgetDetail()
  {
    return $this->belongsTo(BudgetDetail::class, 'budget_detail_id');
  }

  public function payment()
  {
    return $this->belongsTo(Payment::class, 'payment_id');
  }

  public function parent()
  {
    return $this->belongsTo(ApprovalLog::class, 'parent_id');
  }

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