import {
  SubjectType,
  VisibilityType,
  type SubjectType as SubjectTypeCode,
  type VisibilityType as VisibilityTypeCode,
} from "../../shared/api/enums";
import type {
  PermissionDetail,
  PermissionEntry,
  SavePermissionEntry,
  SavePermissionsRequest,
} from "./permissionTypes";

export interface PermissionDraft {
  visibilityType: VisibilityTypeCode;
  documentRowVersion: number;
  entries: PermissionEntry[];
}

export function clonePermissionDraft(
  detail: PermissionDetail,
): PermissionDraft {
  return {
    visibilityType: detail.visibilityType,
    documentRowVersion: detail.documentRowVersion,
    entries: detail.entries.map((entry) => ({ ...entry })),
  };
}

export function createPermissionEntry(
  subjectType: SubjectTypeCode,
  subjectId: string,
  subjectName: string,
): PermissionEntry {
  return {
    id: `draft-${subjectType}-${subjectId}`,
    subjectType,
    subjectId,
    subjectName,
    canView: true,
    canDownload: false,
    canEdit: false,
    canManagePermission: false,
    canDelete: false,
  };
}

export function hasDuplicateSubjects(
  entries: readonly PermissionEntry[],
): boolean {
  const keys = entries.map((entry) => `${entry.subjectType}:${entry.subjectId}`);
  return new Set(keys).size !== keys.length;
}

export function transitionVisibility(
  entries: readonly PermissionEntry[],
  visibilityType: VisibilityTypeCode,
): PermissionEntry[] {
  if (visibilityType === VisibilityType.ALL_AUTHENTICATED) return [];
  if (visibilityType === VisibilityType.ORGANIZATION) {
    return entries
      .filter((entry) => entry.subjectType === SubjectType.ORG)
      .map((entry) => ({ ...entry }));
  }
  return entries.map((entry) => ({ ...entry }));
}

function toSaveEntry(entry: PermissionEntry): SavePermissionEntry {
  return {
    subjectType: entry.subjectType,
    subjectId: entry.subjectId,
    canView: entry.canView,
    canDownload: entry.canDownload,
    canEdit: entry.canEdit,
    canManagePermission: entry.canManagePermission,
    canDelete: entry.canDelete,
  };
}

export function buildSavePermissionsRequest(
  draft: PermissionDraft,
): SavePermissionsRequest {
  if (hasDuplicateSubjects(draft.entries)) {
    throw new Error("同一权限主体不能重复添加");
  }
  const entries = transitionVisibility(draft.entries, draft.visibilityType);
  if (
    draft.visibilityType === VisibilityType.ORGANIZATION &&
    entries.length === 0
  ) {
    throw new Error("组织可见范围至少需要一个组织");
  }
  return {
    visibilityType: draft.visibilityType,
    documentRowVersion: draft.documentRowVersion,
    entries: entries.map(toSaveEntry),
  };
}

