<?php

namespace App\Http\Controllers\Admin;

use Carbon\Carbon;
use Inertia\Inertia;
use App\Utils\Helper;
use App\Models\Doctor;
use App\Enums\UserType;
use App\Models\Patient;
use App\Enums\ActionType;
use Illuminate\Http\Request;
use App\Models\MedicalRecord;
use Illuminate\Validation\Rule;
use App\Enums\PublishStatusType;
use Illuminate\Support\Facades\DB;
use App\Http\Controllers\Controller;

class MedicalRecordController extends Controller
{
  public $adminRole = [UserType::Admin];
  public $isAdmin = false;
  public $page = null;

  public function __construct()
  {
    $this->middleware(function ($request, $next) {
      $user = auth()->user();
      $this->page = $this->getPage($request);
      $this->isAdmin = $user && in_array($user->role, $this->adminRole);
      return $next($request);
    });
  }

  public function index(Request $request)
  {
    $medicalRecords = MedicalRecord::with('doctor','patient')
      ->when($request->filled("doctor_id"), function ($query) use ($request) {
        $query->where("doctor_id", "=", $request->doctor_id);
      })
      ->when($request->filled("institute"), function ($query) use ($request) {
        $query->whereRelation("doctor","institute", "=", $request->institute);
      })
      ->filter($request)
      ->paginate(20);

    $data = [
      "title" => "{$this->page["label"]}",
      "page" => $this->page,
      "medical_records" => collect($medicalRecords),
      "isAdmin" => $this->isAdmin,
    ];

    $data["doctor_id"] = Doctor::select(["id as value", "name as label"])->get()->toArray();
    $data["patient_id"] = Patient::select(["id as value", "name as label"])->get()->toArray();
    $data["institute"] = Doctor::select("institute as value", "institute as label")->get()->toArray();

    return Inertia::render("Admin/MedicalRecord/Index", $data);
  }

  protected function getFormData($request, $medicalRecord = null)
  {
    $defaultValues = ["patient_id"];

    if (!empty($medicalRecord)) {
      $array = collect($medicalRecord->toArray())->only($defaultValues)->toArray();
      $request->merge([...$array, ...$request->all()]);
    }

    $page = $this->getPage($request);
    $doctors = Doctor::select("id as value", DB::raw("CONCAT(name, ' - ', institute) AS label"))->get();
    $patients = Patient::select("id as value", "name as label")->get();

    $selected_patient = null;
    $selected_medical_records = null;
    if ($request->filled('patient_id')) {
      $selected_patient = Patient::where("id", $request->patient_id)->first();
      $selected_medical_records = MedicalRecord::where("patient_id", $request->patient_id)->orderBy("id", "desc")->get();
    }

    foreach ($defaultValues as $value) {
      if ($request->filled($value)) {
        $page["fields"] = collect($page["fields"])->map(function ($field) use ($request, $value) {
          if ($field["name"] == $value) {
            $field["defaultValue"] = $request->input($value);
          }
          return $field;
        })->toArray();
      }
    }

    $data = [
      "isAdmin" => $this->isAdmin,
      "page" => $page,
      "doctors" => $doctors,
      "patients" => $patients,
      "selected_patient" => $selected_patient,
      "selected_medical_records" => $selected_medical_records,
      "status" => PublishStatusType::getValues(),
    ];

    return $data;
  }

  public function create(Request $request)
  {
    $formData = $this->getFormData($request);
    $data = [...$formData, "title" => "Tambah {$this->page["label"]}"];

    return Inertia::render("Admin/MedicalRecord/Create", $data);
  }

  public function edit($id, Request $request)
  {
    $medicalRecord = MedicalRecord::where("id", $id)->first();
    $authorize = $this->getAuthorize($request, $medicalRecord, ActionType::Update);
    if ($authorize instanceof \Illuminate\Http\RedirectResponse) {
      return $authorize;
    }

    $formData = $this->getFormData($request, $medicalRecord);

    $data = [...$formData, "title" => "Edit {$this->page["label"]}", $this->page["name"] => $medicalRecord];
    return Inertia::render("Admin/MedicalRecord/Edit", $data);
  }

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

    DB::beginTransaction();
    try {
      $validationResult = $this->processValidateData($validatedData, $request);
      if ($validationResult instanceof \Illuminate\Http\RedirectResponse) {
        return $validationResult;
      }

      [$validatedData] = $validationResult;
      MedicalRecord::create($validatedData);

      DB::commit();
      return redirect(\App\Utils\Helper::getRefurl(request()) ?? $this->page["url"])->with("success", "Tambah {$this->page["label"]} Baru Berhasil");
    } catch (\Throwable $th) {
      DB::rollBack();
      return redirect()
        ->back()
        ->with("error", "Tambah {$this->page["label"]} Baru Gagal. Kesalahan sistem internal");
    }
  }

  public function update($id, Request $request)
  {
    $validatedData = $request->validate($this->validation($request, $id)["validation"]);

    DB::beginTransaction();
    try {
      $medicalRecord = MedicalRecord::where("id", $id)->first();

      $authorize = $this->getAuthorize($request, $medicalRecord, ActionType::Update);
      if ($authorize instanceof \Illuminate\Http\RedirectResponse) {
        return $authorize;
      }

      $validationResult = $this->processValidateData($validatedData, $request);
      if ($validationResult instanceof \Illuminate\Http\RedirectResponse) {
        return $validationResult;
      }

      [$validatedData] = $validationResult;
      $medicalRecord->update($validatedData);

      DB::commit();
      return redirect(\App\Utils\Helper::getRefurl(request()) ?? $this->page["url"])->with("success", "Update {$this->page["label"]} Berhasil");
    } catch (\Throwable $th) {
      DB::rollBack();
      return redirect()
        ->back()
        ->with("error", "Update {$this->page["label"]} Gagal. Kesalahan sistem internal");
    }
  }

  protected function processValidateData($validatedData, $request)
  {
    $validatedData['user_id'] = auth()->id();
    return [$validatedData];
  }

  public function destroy($id, Request $request)
  {
    DB::beginTransaction();
    try {
      $medicalRecord = MedicalRecord::where("id", $id)->first();

      $authorize = $this->getAuthorize($request, $medicalRecord, ActionType::Delete);
      if ($authorize instanceof \Illuminate\Http\RedirectResponse) {
        return $authorize;
      }

      $message = "Hapus {$this->page["label"]} Berhasil";
      $medicalRecord->delete();

      DB::commit();
      return redirect(\App\Utils\Helper::getRefurl(request()) ?? $this->page["url"])->with("success", $message);
    } catch (\Throwable $th) {
      DB::rollBack();
      return redirect()
        ->back()
        ->with("error", "Hapus {$this->page["label"]} Gagal. {$this->page["label"]} ini masih digunakan oleh fitur lain");
    }
  }

  protected function getAuthorize($request, $data = null, $action = ActionType::Read)
  {
    $user = auth()->user();
    if ($user->role == UserType::Admin) {
      return true;
    }

    $actionLabels = Helper::getEnumTranslation(ActionType::class, "id");
    $forbiddenMessage = "Anda tidak diperbolehkan {$actionLabels[$action]} {$this->page["label"]} ini";

    return Helper::redirectBack("error", $forbiddenMessage);
  }

  protected function getPage($request, $id = null)
  {
    $fields = \App\Utils\Helper::getFormFields($this->validation($request));

    $page = [
      "name" => "medical_records",
      "label" => "Rekam Medis",
      "url" => "/admin/medical_records",
      "data" => null,
      "fields" => $fields,
    ];

    return $page;
  }

  protected function validation($request, $id = null)
  {
    return [
      "validation" => [
        "patient_id" => "required|integer|exists:patients,id",
        "doctor_id" => "required|integer|exists:doctors,id",
        "date" => "required|date",
        "complaint" => "required|string",
        "note" => "nullable|string",
        "treatment" => "nullable|string",
      ],
      "default" => [],
    ];
  }
}
