<?php

namespace App\Http\Controllers\Admin;

use App\Models\User;
use Inertia\Inertia;
use App\Utils\Helper;
use App\Enums\UserType;
use Laravolt\Avatar\Avatar;
use Illuminate\Http\Request;
use App\Enums\OriginStatusType;
use Illuminate\Validation\Rule;
use Illuminate\Validation\Rules;
use Illuminate\Support\Facades\DB;
use App\Http\Controllers\Controller;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Storage;
use App\Http\Services\SoftDeleteService;

class UsersController 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)
  {
    $users = User::when($request->filled("role"), function ($query) use ($request) {
        $query->where("role", $request->role);
      })
      ->when($request->filled("status"), function ($query) use ($request) {
        $query->where("status", $request->status);
      })
      ->filter($request)
      ->paginate(50);

    $users = collect($users);

    $data = [
      "title" => "{$this->page['label']}",
      "role" => [UserType::Admin, UserType::Editor],
      "users" => $users,
      "page" => $this->page,
      "status" => OriginStatusType::getValues(),
      "isAdmin" => $this->isAdmin,
    ];

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

  protected function getFormData($request)
  {
    $data = [
      "status" => OriginStatusType::getValues(),
      "page" => $this->page,
      "roles" => [UserType::Admin, UserType::Editor],
      "isAdmin" => $this->isAdmin,
    ];
    return $data;
  }

  public function create()
  {

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

    return Inertia::render("Admin/Users/Create", $data);
  }
  public function edit(User $user)
  {
    if (!$user) return Helper::redirectBack('error','Data tidak ditemukan');  
    if (!$this->getAuthorize(request(), $user)) return redirect()->back()->with("error", "Anda tidak dapat mengakses fitur ini");

    $formData = $this->getFormData(request());
    $data = [
      ...$formData,
      "title" => "Edit {$this->page['label']}",
      "user" => $user,
    ];

    return Inertia::render("Admin/Users/Edit", $data);
  }

  public function store(Request $request)
  {
    if (!$this->getAuthorize($request)) return redirect()->back()->with("error", "Anda tidak dapat mengakses fitur ini");

    $validate = $request->validate($this->validation($request)["validation"]);

    DB::beginTransaction();
    try {
      if (!$this->isAdmin) {
        if (!in_array($validate['role'], [UserType::User])) return redirect()->back()->with("error", "Role {$validate['role']} tidak dapat ditambahkan oleh anda");
      }

      if ($request->file("picture")) {
        $file = Storage::disk("public")->put("picture", $request->file("picture"));
        $validate["picture"] = $file ? "/storage/$file" : null;
      }

      if (!$validate["picture"]) {
        $avatar = new Avatar();
        $validate["picture"] = $avatar->create($request->name)->setBackground("#7842f5")->setForeground("#ffffff")->setDimension(200)->setFontSize(100)->toBase64();
      }

      $validate["password"] = Hash::make($request->password);
      $user = User::create($validate);

      $email = explode("@", $request->email);
      $username = $email[0] . $user->id;
      $user->username  = preg_replace("/[^A-Za-z0-9]/", "-", $username);
      $user->save();

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

  public function update($id, Request $request)
  {
    if (!$this->getAuthorize($request)) return redirect()->back()->with("error", "Anda tidak dapat mengakses fitur ini");

    if ($request->restore_data == '1')
      return SoftDeleteService::restore("users", $id, $this->page);

    $validate = $request->validate($this->validation($request, $id)["validation"]);

    DB::beginTransaction();
    try {
      if (!$this->isAdmin) {
        if (!in_array($validate['role'], [UserType::User])) return redirect()->back()->with("error", "Role {$validate['role']} tidak dapat ditambahkan oleh anda");
      }

      $user = User::where("id", $id)->first();
      if (!$user) return Helper::redirectBack('error','Data tidak ditemukan');  

      if ($request->file("picture")) {
        $file = Storage::disk("public")->put("picture", $request->file("picture"));
        $validate["picture"] = $file ? "/storage/$file" : $user->picture;
        if ($file && Storage::disk("public")->exists(substr($user->picture, 9))) {
          Storage::disk("public")->delete(substr($user->picture, 9));
        }
      } else {
        unset($validate["picture"]);
      }

      if ($request->password) {
        $validate["password"] = Hash::make($request->password);
      } else {
        unset($validate["password"]);
      }

      $user->update($validate);

      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", "Kesalahan Server. Update {$this->page['label']} gagal");
    }
  }

  public function destroy($id)
  {
    DB::beginTransaction();
    try {
      $user = User::whereId($id)->withTrashed()->first();
      if (!$user) return Helper::redirectBack('error','Data tidak ditemukan');  

      if (!$this->getAuthorize(request(), $user)) return redirect()->back()->with("error", "Anda tidak dapat mengakses fitur ini");

      if ($user->deleted_at) {
        $user->forceDelete();
      } else {
        $user->username = "$user->username|deleted:" . time();
        $user->email = "$user->email|deleted:" . time();
        $user->save();
        $user->delete();
      }


      DB::commit();
      return redirect($this->page['url'])->with("success", "Hapus {$this->page['label']} berhasil");
    } catch (\Throwable $th) {
      DB::rollBack();
      return redirect()->back()->with("error", "Hapus {$this->page['label']} gagal, {$this->page['label']} ini masih digunakan fitur lain");
    }
  }

  protected function getAuthorize($request, $user = null)
  {
    if ($this->isAdmin) return true;
    if (!$user) return true;

    $allowedEditedRole = [UserType::User];
    if (!in_array($user->role, $allowedEditedRole)) return false;
    return true;
  }

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

    $page = [
      "name" => "users",
      "label" => "Pengguna",
      "url" => "/admin/users",
      "data" => null,
      "fields" => $fields,
    ];

    return $page;
  }
  protected function validation($request, $id = null)
  {
    return [
      "validation" => [
        "name" => "required|string|max:255",
        "username" => ["nullable", "string", "max:255", Rule::unique(User::class, "username")->ignore($id)],
        "email" => "required|string|email|max:255|unique:" . User::class . ",email," . $id,
        "password" => ["nullable", "confirmed", Rules\Password::defaults()],
        "role" => "required|string|max:255",
        "picture" => ["nullable", ...[is_file($request->picture) ? ["image", "mimes:jpeg,png,jpg,gif,svg,webp,avif", "max:2048"] : []]],
        "status" => "nullable",
        "phone" => ["nullable", "numeric", "digits_between:10,13", "starts_with:08,02"],
      ],
      "default" => [
        "status" => OriginStatusType::Active,
      ]
    ];
  }
}