<?php

namespace App\Http\Controllers\Admin;

use App\Models\Bank;
use App\Models\User;
use App\Utils\Helper;
use App\Enums\UserType;
use App\Models\Payment;
use App\Models\UserBank;
use App\Enums\ModuleType;
use App\Enums\PaymentType;
use App\Models\Department;
use Illuminate\Http\Request;
use App\Enums\ActionStatusType;
use App\Enums\OriginStatusType;
use App\Enums\PaymentMethodType;
use App\Enums\PaymentStatusType;
use Illuminate\Support\Facades\DB;
use App\Enums\TransactionStatusType;
use App\Http\Services\ApprovalLogService;
use App\Http\Controllers\Core\BaseResourceController;

class PaymentController extends BaseResourceController
{
  protected $model = Payment::class;

  protected function indexQuery($query, Request $request)
  {
    $query->with(["budget", "attachments", "reviewer:id,name", "transaction" => ["quantityUnits.unitType", "attachments", "vendor"]]);
    $query->when($request->filled("type"), fn($q) => $q->where("type", $request->input('type')));
    $query->when($request->filled("method"), fn($q) => $q->where("method", $request->input('method')));
    $query->when($request->filled("status"), fn($q) => $q->where("status", $request->input('status')));

    return $query;
  }

  protected function indexData(Request $request, $isFormData = true): array
  {
    $paymentSumQuery = clone $this->mainQuery;
    $paymentSum = $paymentSumQuery->select([
      DB::raw("
            COALESCE(SUM(amount), 0)  AS amount_total
        "),
    ])
      ->first();

    return [
      "paymentSum" => [
        "amount_total" => intval($paymentSum->amount_total ?? 0),
      ],
      ...parent::indexData($request, $isFormData),
    ];
  }

  protected function getPage(Request $request, $id = null): array
  {
    $page = [
      "name" => "payments",
      "inertia" => "Admin/Payment",
      "label" => "Pembayaran",
      "url" => "/admin/payments",
      "fields" => Helper::getFormFields($this->validation($request)),
    ];

    return $page;
  }

  protected function validation(Request $request, $id = null): array
  {
    return [
      "validation" => [
        "company_id" => "required|integer|exists:companies,id",
        "department_id" => "required|integer|exists:departments,id",
        "budget_id" => "required|integer|exists:budgets,id",
        "user_review_id" => "required|integer|exists:users,id",
        "user_bank_id" => "required|integer|exists:user_banks,id",
        "bank_id" => "required|integer|exists:banks,id",
        "code" => "required|string",
        "type" => "required|string",
        "method" => "required|string",
        "amount" => "required|integer",
        "payment_date" => "required|date",
        "due_date" => "required|date",
        "cheque_number" => "required|string",
        "description" => "nullable|string",
        "status" => "required|string",
        "status_message" => "nullable|string",
        "review_at" => "nullable|date",
      ],
      "default" => [
        "type" => PaymentType::Full,
        "method" => PaymentMethodType::EBanking,
      ],
    ];
  }

  protected function getFormData(Request $request, $model = null): array
  {
    $formData = [];
    $status = PaymentStatusType::getValues();
    $type = PaymentType::getValues();
    $method = PaymentMethodType::getValues();

    if ($this->isFormPage) {
      $formData['users'] = User::selectOptions()->where('status', OriginStatusType::Active)->get();
      $formData['user_banks'] = UserBank::selectOptions("id", "account_name")->where('status', OriginStatusType::Active)->get();
      $formData['banks'] = Bank::selectOptions()->where('status', OriginStatusType::Active)->get();
    }

    return [
      "status" => $status,
      "type" => $type,
      "method" => $method,

      ...parent::getFormData($request, $model),
      ...$formData,
    ];
  }
  protected function actionUpdate($id, Request $request)
  {
    if ($request->rejected == '1')
      return $this->updateStatus(PaymentStatusType::Rejected, $request);
    return null;
  }

  public function updateStatus($status, Request $request)
  {
    $allowedRoles = match ($status) {
      PaymentStatusType::Rejected => [UserType::Director, UserType::Manager],
      default => []
    };

    if (!in_array(auth()->user()->role, $allowedRoles))
      return redirect()->back()->with("error", "Anda tidak dapat mengakses fitur ini");

    // Additional Validations
    $validate = [];
    if ($status === PaymentStatusType::Rejected) {
      $validate = $request->validate([
        "rejected_message" => "required|string",
      ]);
    }

    DB::beginTransaction();
    try {
      $modelClass = $this->model;
      $query = $modelClass::query();
      $query->with("transaction");
      $query = $this->selectParams($query, $request);
      $payment = $query->first();

      // Status Updates
      $payment->status = $status;

      if (in_array($status, [PaymentStatusType::Paid, PaymentStatusType::Rejected])) {
        $payment->user_review_id = auth()->id();
        $payment->review_at = now()->toDateTimeString();
      }
      $note = "";
      if ($status === PaymentStatusType::Rejected) {
        $note = $validate["rejected_message"];
      }

      if ($note) {
        $payment->status_message = $note;
      }

      $payment->save();

      if ($payment->status === PaymentStatusType::Rejected && !empty($payment->transaction)) {
        $payment->transaction->update([
          'status' => TransactionStatusType::Rejected,
          'status_message' => $note
        ]);
      }

      $department = Department::active($request)->first();
      (new ApprovalLogService())->create($request, $payment, ModuleType::Payment, ActionStatusType::Reject, [
        'is_finance' => $department?->is_finance ?? false,
        'note' => $note
      ]);

      DB::commit();
      return redirect(Helper::getRefurl(request()) ?? $this->page['url'])->with("success", "Update status {$this->page["label"]} berhasil");
    } catch (\Throwable $th) {
      DB::rollBack();
      return redirect()->back()->with("error", "Kesalahan Server. Update status {$this->page["label"]} gagal");
    }
  }
}
