<?php

namespace App\Http\Services;

use App\Models\User;
use App\Models\Budget;
use App\Enums\UserType;
use App\Models\Payment;
use App\Enums\ModuleType;
use App\Models\Department;
use App\Models\ApprovalLog;
use Illuminate\Http\Request;
use App\Enums\ActionStatusType;
use App\Enums\BudgetStatusType;
use App\Enums\OriginStatusType;
use App\Enums\PaymentStatusType;
use App\Enums\UserDepartmentType;
use App\Http\Services\NotificationService;

class ApprovalLogService
{
  /**
   * Create an approval log entry.
   *
   * @param Request $request
   * @param mixed $model 
   * @param mixed $moduleType
   * @param mixed $action 
   * @param array $options 
   * @return ApprovalLog|null
   */
  public function create(Request $request, $model, $moduleType, $action = null, array $options = [])
  {
    $isNotify = isset($options['is_notify']) ? $options['is_notify'] : true;

    $status = $model->status ?? null;
    $user = auth()->user();
    if (!empty($options['sender_user_id'])) {
      $user = User::find($options['sender_user_id']);
    }

    if (!$action) {
      if ($model instanceof Payment) {
        $action = match ($status?->value ?? $status) {
          PaymentStatusType::Paid => ActionStatusType::Approve,
          PaymentStatusType::Review => ActionStatusType::Process,
          PaymentStatusType::Rejected => ActionStatusType::Reject,
          default => null,
        };
      } else {
        $action = match ($status?->value ?? $status) {
          BudgetStatusType::Review => ActionStatusType::Submit,
          BudgetStatusType::Approved => ActionStatusType::Approve,
          BudgetStatusType::Rejected => ActionStatusType::Reject,
          BudgetStatusType::Revision => ActionStatusType::Revise,
          default => null,
        };
      }
    }

    if (!$action) {
      return null;
    }

    $approvalLevel = null;
    if ($action == ActionStatusType::Approve && !($model instanceof Payment)) {
      $approvalLevel = $user->role;
    }

    if (!$approvalLevel) {
      $approvalLevel = match ($user->role) {
        UserType::User => UserDepartmentType::Manager,
        UserType::Manager => UserDepartmentType::Director,
        default => UserDepartmentType::Manager,
      };
    }

    if ($model instanceof Payment && $action == ActionStatusType::Approve) {
      $approvalLevel = null;
    }

    if ($model instanceof Payment && $action == ActionStatusType::Reject) {
      $approvalLevel = $user->role;
    }

    if ($action == ActionStatusType::Revise) {
      $approvalLevel = match ($user->role) {
        UserType::Manager => UserDepartmentType::User,
        UserType::Director => UserDepartmentType::Manager,
        default => UserDepartmentType::User,
      };
    }

    $department = Department::active($request)->first();
    $approvalDepartmentId = $department?->id;

    if (!empty($options['target_finance_department'])) {
      $financeDepartment = Department::where([
        'company_id' => $department->company_id,
        'is_finance' => true,
        'status' => OriginStatusType::Active
      ])->first();
      $approvalDepartmentId = $financeDepartment?->id;
    }

    $budgetId = $options['budget_id'] ?? ($model->budget_id ?? ($model instanceof Budget ? $model->id : null));
    $paymentId = $options['payment_id'] ?? ($model instanceof Payment ? $model->id : null);
    $budgetDetailId = $options['budget_detail_id'] ?? ($model instanceof BudgetDetail ? $model->id : null);

    if ($moduleType == ModuleType::BudgetDetail) {
      $budgetId = null;
    }

    $data = [
      'user_id' => $user->id,
      'department_id' => $department?->id,
      'approval_department_id' => $approvalDepartmentId,
      'parent_id' => $options['parent_id'] ?? null,
      'budget_id' => $budgetId,
      'budget_detail_id' => $budgetDetailId,
      'payment_id' => $paymentId,
      'module_type' => $moduleType,
      'action' => $action,
      'submit_level' => $user->role,
      'approval_level' => $approvalLevel,
      'is_finance' => $options['is_finance'] ?? false,
      'note' => $options['note'] ?? $request->note ?? $request->status_message ?? ($request->custom_note ?? ""),
      'ip_address' => $request->ip(),
      'user_agent' => $request->userAgent(),
      'detail' => $options['detail'] ?? null,
    ];

    $approvalLog = ApprovalLog::create($data);
    if ($isNotify) {
      (new NotificationService())->create($model, $action, $approvalLog->id, $user, $approvalDepartmentId, $approvalLevel);
    }

    return $approvalLog;
  }
}
