import {
  CategoryType,
  EnabledStatus,
  type CategoryType as CategoryTypeCode,
  type EnabledStatus as EnabledStatusCode,
} from "../../shared/api/enums";
import type { Id } from "../../shared/api/types";

export interface CategoryNode {
  id: Id;
  categoryCode: string;
  categoryName: string;
  categoryType: CategoryTypeCode;
  parentId: Id | null;
  categoryPath: string;
  sortNo: number;
  documentCount: number;
  rowVersion: number;
  children: CategoryNode[];
}

export interface CategoryTreeQuery {
  keyword?: string;
  status?: EnabledStatusCode;
}

export interface CreateCategoryRequest {
  categoryCode: string;
  categoryName: string;
  categoryType: CategoryTypeCode;
  parentId: Id | null;
  sortNo: number;
}

export interface UpdateCategoryRequest {
  categoryName: string;
  categoryType: CategoryTypeCode;
  parentId: Id | null;
  sortNo: number;
  rowVersion: number;
}

export interface DeleteCategoryResult {
  id: Id;
  deleted: true;
}

function isRecord(value: unknown): value is Record<string, unknown> {
  return !!value && typeof value === "object" && !Array.isArray(value);
}

function isId(value: unknown): value is Id {
  return typeof value === "string" && /^[0-9]+$/.test(value);
}

function isNonNegativeInteger(value: unknown): value is number {
  return (
    typeof value === "number" &&
    Number.isInteger(value) &&
    value >= 0
  );
}

function isEnumValue<T extends Record<string, string>>(
  values: T,
  value: unknown,
): value is T[keyof T] {
  return (
    typeof value === "string" &&
    (Object.values(values) as string[]).includes(value)
  );
}

export function isCategoryNode(value: unknown): value is CategoryNode {
  if (!isRecord(value)) return false;
  return (
    isId(value.id) &&
    typeof value.categoryCode === "string" &&
    typeof value.categoryName === "string" &&
    isEnumValue(CategoryType, value.categoryType) &&
    (value.parentId === null || isId(value.parentId)) &&
    typeof value.categoryPath === "string" &&
    isNonNegativeInteger(value.sortNo) &&
    isNonNegativeInteger(value.documentCount) &&
    isNonNegativeInteger(value.rowVersion) &&
    Array.isArray(value.children) &&
    value.children.every(isCategoryNode)
  );
}

export function isCategoryTree(value: unknown): value is CategoryNode[] {
  return Array.isArray(value) && value.every(isCategoryNode);
}

export function isDeleteCategoryResult(
  value: unknown,
): value is DeleteCategoryResult {
  return (
    isRecord(value) &&
    isId(value.id) &&
    value.deleted === true
  );
}

export function isEnabledStatus(value: unknown): value is EnabledStatusCode {
  return isEnumValue(EnabledStatus, value);
}

