"use client";

import { useCallback, useEffect, useState } from "react";

import {
  createRole,
  deleteRole,
  getPermissions,
  getRoleDetail,
  getRoles,
  updateRole,
} from "@/features/role/service/role-service";
import type {
  Permission,
  Role,
  RoleDetail,
  SaveRolePayload,
} from "@/features/role/role-data";

type UseRolesResult = {
  roles: Role[];
  permissions: Permission[];
  isLoading: boolean;
  saving: boolean;
  error: string | null;
  loadRoles: () => Promise<void>;
  getRoleDetail: (id: number) => Promise<RoleDetail>;
  createRole: (payload: SaveRolePayload) => Promise<void>;
  updateRole: (id: number, payload: SaveRolePayload) => Promise<void>;
  deleteRole: (id: number) => Promise<void>;
};

export function useRoles(): UseRolesResult {
  const [roles, setRoles] = useState<Role[]>([]);
  const [permissions, setPermissions] = useState<Permission[]>([]);
  const [isLoading, setIsLoading] = useState(true);
  const [saving, setSaving] = useState(false);
  const [error, setError] = useState<string | null>(null);

  const loadRoles = useCallback(async () => {
    try {
      setIsLoading(true);
      setError(null);

      const roleList = await getRoles();

      setRoles(roleList);
    } catch (requestError) {
      setRoles([]);
      setError(
        requestError instanceof Error
          ? requestError.message
          : "Unable to load roles.",
      );
    } finally {
      setIsLoading(false);
    }
  }, []);

  useEffect(() => {
    let ignore = false;

    getRoles()
      .then((roleList) => {
        if (!ignore) {
          setRoles(roleList);
          setError(null);
        }
      })
      .catch((requestError) => {
        if (!ignore) {
          setRoles([]);
          setError(
            requestError instanceof Error
              ? requestError.message
              : "Unable to load roles.",
          );
        }
      })
      .finally(() => {
        if (!ignore) setIsLoading(false);
      });

    return () => {
      ignore = true;
    };
  }, []);

  useEffect(() => {
    let ignore = false;

    getPermissions()
      .then((list) => {
        if (!ignore) setPermissions(list);
      })
      .catch(() => undefined);

    return () => {
      ignore = true;
    };
  }, []);

  const handleCreate = useCallback(
    async (payload: SaveRolePayload) => {
      setSaving(true);
      try {
        await createRole(payload);
        await loadRoles();
      } finally {
        setSaving(false);
      }
    },
    [loadRoles],
  );

  const handleUpdate = useCallback(
    async (id: number, payload: SaveRolePayload) => {
      setSaving(true);
      try {
        await updateRole(id, payload);
        await loadRoles();
      } finally {
        setSaving(false);
      }
    },
    [loadRoles],
  );

  const handleDelete = useCallback(
    async (id: number) => {
      setSaving(true);
      try {
        await deleteRole(id);
        await loadRoles();
      } finally {
        setSaving(false);
      }
    },
    [loadRoles],
  );

  return {
    roles,
    permissions,
    isLoading,
    saving,
    error,
    loadRoles,
    getRoleDetail,
    createRole: handleCreate,
    updateRole: handleUpdate,
    deleteRole: handleDelete,
  };
}
