<?php

namespace App\Http\Controllers\Admin\Module;

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\Attachment;
use App\Models\Department;
use App\Enums\UserBankType;
use App\Models\ApprovalLog;
use Illuminate\Http\Request;
use App\Enums\ActionStatusType;
use App\Http\Services\ApprovalLogService;
use App\Enums\PaymentMethodType;
use App\Enums\PaymentStatusType;
use App\Enums\UserDepartmentType;
use Illuminate\Support\Facades\DB;
use App\Enums\AttachmentContentType;
use App\Enums\TransactionStatusType;
use Illuminate\Support\Facades\Storage;
use App\Http\Controllers\Core\BaseResourceController;

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

  protected function indexData(Request $request, $isFormData = true): array
  {
    $payment = Payment::with([
      'department',
      'companyBank',
      'userBank',
      'reviewer',
      'budget' => function ($query) {
        $query->withPaidAmount()->withPendingPayment()->with('user');
      }
    ])
      ->find($request->route('payment_id'));

    return [
      'payment' => $payment,
      "user_banks" => UserBank::join('banks', 'user_banks.bank_id', '=', 'banks.id')
        ->where('user_banks.type', UserBankType::Personal)
        ->whereNull('banks.deleted_at')
        ->select([
          'user_banks.id as value',
          DB::raw("CONCAT(banks.name, ' - ', user_banks.account_number, ' - ', user_banks.account_name) as label")
        ])
        ->get(),
      "company_banks" => UserBank::join('banks', 'user_banks.bank_id', '=', 'banks.id')
        ->where('user_banks.type', UserBankType::Company)
        ->whereNull('banks.deleted_at')
        ->select([
          'user_banks.id as value',
          DB::raw("CONCAT(banks.name, ' - ', user_banks.account_number, ' - ', user_banks.account_name) as label")
        ])
        ->get(),
      "types" => PaymentType::getValues(),
      "methods" => PaymentMethodType::getValues(),
    ];
  }

  protected function getPage(Request $request, $id = null): array
  {
    return [
      "name" => "payment_approvals",
      "inertia" => "Admin/Module/PaymentApproval",
      "label" => "Approval Pembayaran",
      "url" => "/admin/payments/{$request->route('payment_id')}/payment_approvals",
      "fields" => Helper::getFormFields($this->validation($request)),
    ];
  }

  protected function validation(Request $request, $id = null): array
  {
    $isDirector = auth()->user()->role == UserType::Director;
    $directorRule = $isDirector ? "required" : "nullable";

    return [
      "validation" => [
        "user_bank_id" => "required|integer|exists:user_banks,id",
        "company_bank_id" => "required|integer|exists:user_banks,id",
        "type" => "$directorRule|string",
        "method" => "required|string",
        "amount" => "$directorRule|integer|min:1",
        "payment_date" => "$directorRule|date",
        "due_date" => "$directorRule|date",
        "cheque_number" => "required_if:method," . PaymentMethodType::ChequeGiro,
        "description" => "nullable|string",
        "max_amount" => "nullable|integer",
        "payment_percentage" => "nullable|integer|min:0|max:100",
        'attachment' => [$directorRule, ...[is_file($request->attachment) ? ['image', 'mimes:jpeg,png,jpg,gif,svg,webp,avif', 'max:2048'] : []]],
      ],
      "default" => [],
    ];
  }

  public function store(Request $request)
  {
    $validate = $request->validate($this->validation($request)['validation']);

    DB::beginTransaction();
    try {
      $payment = Payment::with(['transaction', 'budget' => fn($query) => $query->withPaidAmount()])->find($request->route('payment_id'));

      if (!$payment) {
        return redirect()->back()->with("error", "Pembayaran tidak ditemukan.");
      }
      $approvalLog = ApprovalLog::where('payment_id', $payment->id)->latest()->first();
      if ($approvalLog && $approvalLog->action == ActionStatusType::Approve) {
        return redirect()->back()->with("error", "Pembayaran ini sudah disetujui sebelumnya.");
      }

      $payment->fill($validate);
      $payment->review_at = now();
      $payment->user_review_id = auth()->id();

      if (auth()->user()->role == UserType::Manager) {
        $payment->status = PaymentStatusType::Review;
      }
      if (auth()->user()->role == UserType::Director) {
        $payment->status = PaymentStatusType::Paid;
      }

      if ($payment->status == PaymentStatusType::Paid) {
        $budget = $payment->budget;

        $remainingAmount = intval($budget->paid_remaining_amount);
        $paymentAmount = intval($payment->amount);
        if ($paymentAmount > $remainingAmount) {
          return redirect()->back()->with("error", "Nominal pembayaran Rp. " . number_format($paymentAmount, 0, ',', '.') . " melebihi sisa anggaran Rp. " . number_format($remainingAmount, 0, ',', '.'));
        }

        $payment->max_amount = $remainingAmount;
        $payment->payment_percentage = $remainingAmount > 0 ? round(($paymentAmount / $remainingAmount) * 100) : 0;

        if ($payment->payment_percentage == 100) {
          $payment->type = PaymentType::Full;
        }

        $payment->save();
      }

      $payment->save();

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

      if ($request->file('attachment')) {
        $fileExt = $request->file('attachment')->getClientOriginalExtension();
        $safeCode = str_replace('/', '-', $payment->code);
        $fileName = "$safeCode.$fileExt";

        $file = Storage::disk('local')->putFileAs('files/attachments/payments', $request->file('attachment'), $fileName);
        if (!$file)
          return redirect()->back()->with('error', 'Gagal upload file');
        Attachment::create([
          'transaction_id' => null,
          'payment_id' => $payment->id,
          'module_type' => ModuleType::Payment,
          'type' => AttachmentContentType::Image,
          'label' => $payment->code,
          'value' => "/files/attachments/",
          'description' => $payment->description,
          'path' => $file,
        ]);
      }

      (new ApprovalLogService())->create($request, $payment, ModuleType::Payment, null, [
        'is_finance' => true,
        'note' => $request->status_message
      ]);
      DB::commit();

      $message = "Pembayaran berhasil ";
      if ($payment->status == PaymentStatusType::Paid) {
        $message .= "disetujui";
      } else if ($payment->status == PaymentStatusType::Review) {
        $message .= "diajukan";
      }

      return redirect("/admin/payments")->with('success', $message);
    } catch (\Exception $e) {
      DB::rollBack();
      return redirect()->back()->with('error', 'Terjadi kesalahan: ' . $e->getMessage());
    }
  }
}
