import type { AccessToolId, AccessUserRole, AccessUserStatus, AdminAccessMatrixResponse, AdminAccessOpenFga, AdminAccessSummaryResponse, AdminAccessTuple, AdminAccessUserSummary, AdminAccessUsersResponse } from "@/types";

export interface AccessUserRow {
  id: string;
  username: string;
  displayName: string;
  role: AccessUserRole;
  status: AccessUserStatus;
  tupleCount: number;
  toolCount: number;
  tools: Record<AccessToolId, boolean>;
}

export interface AccessToolRow {
  id: AccessToolId;
  label: string;
  allowed: boolean;
}

export interface AccessOpenFgaView {
  mode: AdminAccessOpenFga["mode"];
  storeName: string;
  storeId: string;
  modelId: string;
  valuesRedacted: boolean;
  ready: boolean;
  status: AdminAccessOpenFga["status"];
}

export interface AccessTupleView {
  id: string;
  userId: string;
  relation: string;
  object: string;
  createdByAdminId: string;
  createdAt: string;
}

export interface AccessSummaryView {
  contractVersion: string;
  users: number;
  tuples: number;
  toolTuples: number;
  openfga: AccessOpenFgaView;
  toolIds: AccessToolId[];
}

const TOOL_LABELS: Record<AccessToolId, string> = {
  hwpod: "HWPOD CLI",
  unidesk_ssh: "UniDesk SSH",
  trans_cmd: "trans passthrough",
  github_pr: "GitHub PR"
};

export function normalizeAccessSummary(payload: AdminAccessSummaryResponse | null): AccessSummaryView {
  if (!payload) return emptyAccessSummary();
  return {
    contractVersion: payload.contractVersion,
    users: payload.counts.users,
    tuples: payload.counts.tuples,
    toolTuples: payload.counts.toolTuples,
    openfga: normalizeOpenFga(payload.openfga),
    toolIds: [...payload.supported.toolIds]
  };
}

export function normalizeAccessUsers(payload: AdminAccessUsersResponse | null): AccessUserRow[] {
  return payload?.users.map(normalizeUserRow) ?? [];
}

export function normalizeAccessDetail(payload: AdminAccessMatrixResponse | null): { user: AccessUserRow | null; tools: AccessToolRow[]; tuples: AccessTupleView[]; openfga: AccessOpenFgaView } {
  if (!payload) return { user: null, tools: [], tuples: [], openfga: emptyOpenFga() };
  const user = normalizeUserRow({ user: payload.user, tools: payload.tools, tupleCount: payload.tuples.length });
  return {
    user,
    tools: normalizeTools(payload.tools),
    tuples: payload.tuples.map(normalizeTuple),
    openfga: normalizeOpenFga(payload.openfga)
  };
}

function normalizeOpenFga(value: AdminAccessOpenFga): AccessOpenFgaView {
  return {
    mode: value.mode,
    storeName: value.storeName,
    storeId: value.storeId,
    modelId: value.modelId,
    valuesRedacted: value.valuesRedacted,
    ready: value.ready,
    status: value.status
  };
}

function normalizeTuple(value: AdminAccessTuple, index: number): AccessTupleView {
  return {
    id: `${value.userId}:${value.relation}:${value.object}:${index}`,
    userId: value.userId,
    relation: value.relation,
    object: value.object,
    createdByAdminId: value.createdByAdminId,
    createdAt: value.createdAt
  };
}

export function normalizeTools(value: Record<AccessToolId, boolean>): AccessToolRow[] {
  return (Object.keys(TOOL_LABELS) as AccessToolId[]).map((id) => ({ id, label: TOOL_LABELS[id], allowed: value[id] }));
}

export function accessUserLabel(user: Pick<AccessUserRow, "displayName" | "username" | "id"> | null | undefined): string {
  return user?.displayName.trim() || user?.username.trim() || user?.id.trim() || "unknown";
}

function normalizeUserRow(value: AdminAccessUserSummary): AccessUserRow {
  const tools = { ...value.tools };
  return {
    ...value.user,
    tupleCount: value.tupleCount,
    toolCount: Object.values(tools).filter(Boolean).length,
    tools
  };
}

function emptyOpenFga(): AccessOpenFgaView {
  return { mode: "off", storeName: "", storeId: "", modelId: "", valuesRedacted: true, ready: false, status: "disabled" };
}

function emptyAccessSummary(): AccessSummaryView {
  return { contractVersion: "admin-access-v1", users: 0, tuples: 0, toolTuples: 0, openfga: emptyOpenFga(), toolIds: [] };
}
