<?php

namespace App\Http\Controllers\Admin\Module;

use Inertia\Inertia;
use App\Utils\Helper;
use App\Models\Vendor;
use App\Models\UnitType;
use App\Enums\ModuleType;
use App\Models\Attachment;
use App\Models\Transaction;
use App\Models\BudgetDetail;
use Illuminate\Http\Request;
use App\Enums\BudgetType;
use App\Enums\BudgetStatusType;
use Illuminate\Support\Facades\DB;
use App\Enums\AttachmentContentType;
use App\Enums\TransactionStatusType;
use App\Http\Services\BalanceService;
use Illuminate\Support\Facades\Storage;
use App\Http\Controllers\Core\BaseResourceController;

class TransactionController extends BaseResourceController
{
  protected $model = Transaction::class;

  protected function getPage(Request $request, $id = null): array
  {
    return [
      "name" => "transactions",
      "inertia" => "Admin/Module/Transaction",
      "label" => "Pembelian",
      "url" => "/admin/budgets/{$request->route('budget_id')}/budget_details/{$request->route('budget_detail_id')}/transactions",
      "fields" => Helper::getFormFields($this->validation($request)),
    ];
  }

  protected function validation(Request $request, $id = null): array
  {
    return [
      "validation" => [
        "vendor_id" => "nullable|exists:vendors,id",
        "attachment" => "required|file|mimes:jpg,jpeg,png,webp,avif|max:2048",
        "amount" => "required|numeric",
        "name" => "required|string",
        "price" => "required|numeric",
        "description" => "nullable|string",
        "quantity_unit" => "required|array",
        "quantity_unit.*.quantity" => "required|numeric",
        "quantity_unit.*.unit_type_id" => "required|exists:unit_types,id",
      ],
      "default" => [
        "status" => BudgetStatusType::Approved,
      ],
    ];
  }

  protected function indexQuery($query, Request $request)
  {
    $query->where('budget_detail_id', $request->route('budget_detail_id'));
    $query->with(['vendor', 'user']);
    return $query;
  }

  public function index(Request $request)
  {
    $budgetDetailId = $request->route('budget_detail_id');
    $budgetDetail = BudgetDetail::with('budget', 'quantityUnits.unitType', 'budgetCategory.category')->find($budgetDetailId);

    if (!$budgetDetail) {
      return redirect()->back()->with("error", "Data anggaran detail tidak ditemukan");
    }

    $authorize = $this->getAuthorize($request, $budgetDetail);
    if ($authorize instanceof \Illuminate\Http\RedirectResponse)
      return $authorize;

    $budgetDetail->quantity_unit = $budgetDetail->quantityUnits->map(function ($quantityUnit) {
      return [
        "quantity" => $quantityUnit->quantity,
        "unit_type_id" => $quantityUnit->unit_type_id,
      ];
    });

    $unitTypes = UnitType::selectOptions()->get();
    $page = $this->getPage($request);

    return Inertia::render($page['inertia'] . "/Index", [
      'title' => $page['label'],
      'budgetDetail' => $budgetDetail,
      'vendors' => Vendor::selectOptions()->get(),
      "unit_types" => $unitTypes,
      'page' => $page
    ]);
  }

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

    DB::beginTransaction();
    try {
      $transaction = Transaction::where("budget_detail_id", $request->route('budget_detail_id'))->first();
      if ($transaction) {
        return redirect(route("admin.budgets.budget_details.index", $request->route('budget_id')))->with("error", "Pembelian ini sudah dikirimkan");
      }

      $budgetDetail = BudgetDetail::with('budget', 'quantityUnits.unitType')->find($request->route('budget_detail_id'));

      if (!$budgetDetail) {
        return redirect()->back()->with("error", "Data anggaran detail tidak ditemukan");
      }

      $authorize = $this->validateBudgetType($budgetDetail);
      if ($authorize instanceof \Illuminate\Http\RedirectResponse)
        return $authorize;

      $budgetDetail->quantity_unit = $budgetDetail->quantityUnits->map(function ($quantityUnit) {
        return [
          "quantity" => $quantityUnit->quantity,
          "unit_type_id" => $quantityUnit->unit_type_id,
        ];
      });

      $request->merge([
        'budget_detail_id' => $budgetDetail->id,
        "budget_id" => $budgetDetail->budget_id,
        "budget_category_id" => $budgetDetail->budget_category_id,
      ]);

      $price = intval($request->price);
      $totalQuantity = 0;
      if ($request->has('quantity_unit')) {
        foreach ($request->quantity_unit as $qu) {
          $totalQuantity += intval($qu['quantity']);
        }
      }
      $priceTotal = $price * $totalQuantity;

      $lastTransaction = DB::table("transactions")->select("code")->where('budget_detail_id', $budgetDetail->id)->latest("id")->whereNotNull('code')->first();
      $code = "TRX01";

      if ($lastTransaction) {
        $lastCode = explode("/", $lastTransaction->code);
        $lastCode = $lastCode[0];

        if ($lastCode) {
          $lastCode = str_replace("TRX", "", $lastCode);
          $lastCode = str_pad(intval($lastCode) + 1, 2, "0", STR_PAD_LEFT);
          $code = "TRX{$lastCode}";
        }
      }
      $code .= "/{$budgetDetail->budget->code}";

      $transactionData = [
        'budget_detail_id' => $budgetDetail->id,
        'balance_id' => $budgetDetail->budget->balance_id,
        'user_id' => auth()->id(),
        'vendor_id' => $request->vendor_id,
        'code' => $code,
        'name' => $request->name,
        'description' => $request->description,
        'price' => $price,
        'price_total' => $priceTotal,
        'status' => TransactionStatusType::Success,
        'status_message' => null,
      ];

      $transaction = Transaction::create($transactionData);
      (new BalanceService)->syncBalance($budgetDetail->budget_id);

      foreach ($request->quantity_unit as $qu) {
        $transaction->quantityUnits()->create([
          'transaction_id' => $transaction->id,
          'unit_type_id' => $qu['unit_type_id'],
          'quantity' => $qu['quantity'],
        ]);
      }

      if ($request->file('attachment')) {
        $fileExt = $request->file('attachment')->getClientOriginalExtension();
        $safeCode = str_replace('/', '-', $transaction->code);
        $fileName = "$safeCode.$fileExt";
        $file = Storage::disk('local')->putFileAs('files/attachments/transactions', $request->file('attachment'), $fileName);
        if (!$file)
          return redirect()->back()->with('error', 'Gagal upload file');

        Attachment::create([
          'transaction_id' => $transaction->id,
          'module_type' => ModuleType::Transaction,
          'type' => AttachmentContentType::Image,
          'label' => $transaction->code,
          'value' => "/files/attachments/",
          'description' => "$transaction->name - $transaction->description",
          'path' => $file,
        ]);
      }

      DB::commit();
      return redirect(route("admin.budgets.budget_details.index", $request->route('budget_id')))->with("success", "Pembelian berhasil disimpan");

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

  protected function getAuthorize(Request $request, $data = null, $action = null)
  {
    if ($data?->status?->value !== BudgetStatusType::Approved) {
      return Helper::redirectBack("error", "Detail anggaran belum disetujui");
    }

    if ($data?->budget?->type?->value !== BudgetType::CashAdvance) {
      return Helper::redirectBack("error", "Fitur ini hanya tersedia untuk anggaran jenis Pencairan Dana");
    }

    if (auth()->user()->role !== \App\Enums\UserType::User) {
      return Helper::redirectBack("error", "Anda tidak memiliki akses untuk fitur ini");
    }
  }
}
