<?php

namespace App\Http\Controllers\Admin\Module;

use Inertia\Inertia;
use App\Utils\Helper;
use App\Models\Budget;
use App\Models\Category;
use App\Models\UnitType;
use App\Enums\ActionType;
use Illuminate\Http\Request;
use App\Enums\BudgetStatusType;
use App\Enums\ModuleType;
use App\Http\Services\ApprovalLogService;
use App\Enums\ActionStatusType;
use Illuminate\Support\Facades\DB;
use App\Http\Controllers\Core\BaseResourceController;
use App\Http\Services\BudgetDetailService;

class BudgetRevisionController extends BaseResourceController
{
  protected $model = Budget::class;

  public function index(Request $request)
  {
    $indexValidation = $this->indexValidation($request);
    if ($indexValidation instanceof \Illuminate\Http\RedirectResponse)
      return $indexValidation;

    $budgetId = $request->route('budget_id');
    $budget = Budget::with([
      'user:id,name',
      'budgetCategories' => function ($q) {
        $q->whereHas('budgetDetails', function ($q) {
          $q->where('status', BudgetStatusType::Revision);
        });
      },
      'budgetCategories.budgetDetails' => function ($q) {
        $q->where('status', BudgetStatusType::Revision);
        $q->with('quantityUnits.unitType');
      },
      'budgetCategories.category:id,name',
    ])->find($budgetId);

    $details = $budget->budgetCategories->map(function ($budgetCategory) {
      if ($budgetCategory->budgetDetails->isEmpty())
        return null;

      return [
        "category_id" => $budgetCategory->category_id,
        "items" => $budgetCategory->budgetDetails->map(function ($budgetDetail) {
          return [
            "id" => $budgetDetail->id,
            "name" => $budgetDetail->name,
            "price" => $budgetDetail->price,
            "price_total" => $budgetDetail->price_total,
            "description" => $budgetDetail->description,
            "status" => $budgetDetail->status,
            "status_message" => $budgetDetail->status_message,
            "quantity_unit" => $budgetDetail->quantityUnits->map(function ($quantityUnit) {
              return [
                "quantity" => $quantityUnit->quantity,
                "unit_type_id" => $quantityUnit->unit_type_id,
              ];
            }),
          ];
        }),
      ];
    })->filter()->values();

    $budgetData = $budget->toArray();
    $budgetData['details'] = $details;

    // Select Options
    $unit_types = UnitType::selectOptions()->get();
    $categories = Category::selectOptions()
      ->where('status', \App\Enums\OriginStatusType::Active)
      ->doesntHave('children')
      ->orderByRaw("COALESCE(parent_id, id) ASC")
      ->orderBy("level", "ASC")
      ->orderBy("name", "ASC")
      ->get();

    $page = $this->getPage($request);
    return Inertia::render($page['inertia'] . '/Index', [
      'title' => 'Revisi Anggaran',
      'budget' => $budgetData,
      'isRevision' => true,
      'unit_types' => $unit_types,
      'categories' => $categories,
      'page' => $page
    ]);
  }

  public function store(Request $request)
  {
    $validation = $this->validation($request)["validation"];
    $detailValidation = isset($this->validation($request)["detail_validation"]) ? $this->validation($request)["detail_validation"] : [];
    $validation = array_merge($validation, $detailValidation);

    $request->validate($validation);

    DB::beginTransaction();
    try {
      $budget = Budget::with('budgetCategories', 'budgetDetails')->find($request->route('budget_id'));
      if (!$budget) {
        return redirect()->back()->with('error', 'Anggaran tidak ditemukan.');
      }

      $approvalLog = (new ApprovalLogService())->create($request, $budget, ModuleType::Budget, ActionStatusType::Submit, [
        'note' => null
      ]);

      (new BudgetDetailService())->saveDetails($request, $budget, [
        'is_revision' => true,
        'target_status' => BudgetStatusType::Review,
        'approval_log' => $approvalLog
      ]);

      $budget->status = BudgetStatusType::Review;
      $budget->debit_amount = $budget->budgetCategories()->sum('price_amount_total');
      $budget->credit_amount = 0;
      $budget->save();

      DB::commit();
      return redirect('/admin/budgets')->with('success', 'Revisi anggaran berhasil diajukan.');

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

  protected function getPage(Request $request, $id = null): array
  {
    $page = [
      "name" => "budget",
      "inertia" => "Admin/Module/BudgetRevision",
      "label" => "Revisi Anggaran",
      "url" => "/admin/budgets/{$request->route('budget_id')}/budget_revisions",
      "fields" => Helper::getFormFields($this->validation($request)),
    ];

    return $page;
  }

  protected function validation(Request $request, $id = null): array
  {
    return [
      "validation" => [
        "name" => "required|string",
        "date" => "required|date",
        "year" => "required|string",
        "amount" => "required|integer",
        "description" => "nullable|string",
        "details" => "required|array",
      ],
      "detail_validation" => [
        "details.*.category_id" => "required",
        "details.*.items" => "required|array",
        "details.*.items.*.name" => "required|string",
        "details.*.items.*.price" => "required|integer",
        "details.*.items.*.price_total" => "required|integer",
        "details.*.items.*.description" => "nullable|string",

        "details.*.items.*.quantity_unit" => "array",
        "details.*.items.*.quantity_unit.*.quantity" => "required|integer",
        "details.*.items.*.quantity_unit.*.unit_type_id" => "required",
      ],
      "default" => [
        "status" => BudgetStatusType::Draft,
        "date" => now()->format("Y-m-d"),
        "year" => now()->format("Y"),
      ],
    ];
  }

  protected function indexValidation(Request $request)
  {
    $budget = Budget::withUserAction()
      ->where('id', $request->route('budget_id'))
      ->first();

    if (!$budget)
      return redirect()->back()->with("error", "Data anggaran tidak ditemukan");

    return $this->getAuthorize($request, $budget, ActionType::Read);
  }

  protected function getAuthorize(Request $request, $budget = null, $action = ActionType::Read)
  {
    $user = auth()->user();
    if ($budget->approval_level != $user->role)
      return Helper::redirectBack("error", "Anda belum memiliki hak akses untuk merevisi anggaran ini");

    return true;
  }
}
