import { ContentIds, SystemIds } from '@graphprotocol/grc-20';
import { Config } from '@graphprotocol/hypergraph';
import * as Either from 'effect/Either';
import * as EffectSchema from 'effect/Schema';
import { request } from 'graphql-request';
import { parseGeoId } from '../utils/geo-id.js';
const spaceFields = `
  id
  type
  page {
    name
    relationsList(filter: {
      typeId: { is: "${ContentIds.AVATAR_PROPERTY}"}
    }) {
      toEntity {
        valuesList(filter: {
          propertyId: { is: "${SystemIds.IMAGE_URL_PROPERTY}"}
        }) {
          propertyId
          text
        }
      }
    }
  }
  editorsList {
    memberSpaceId
  }
  membersList {
    memberSpaceId
  }
`;
export const SpaceTypeSchema = /*#__PURE__*/EffectSchema.Union(/*#__PURE__*/EffectSchema.Literal('PERSONAL'), /*#__PURE__*/EffectSchema.Literal('DAO'));
export const PublicSpaceSchema = /*#__PURE__*/EffectSchema.Struct({
  id: EffectSchema.String,
  type: SpaceTypeSchema,
  name: EffectSchema.String,
  avatar: /*#__PURE__*/EffectSchema.optional(EffectSchema.String),
  editorIds: /*#__PURE__*/EffectSchema.Array(EffectSchema.String),
  memberIds: /*#__PURE__*/EffectSchema.Array(EffectSchema.String)
});
const decodeSpace = /*#__PURE__*/EffectSchema.decodeUnknownEither(PublicSpaceSchema);
const getAvatarFromSpace = space => {
  const firstRelation = space.page?.relationsList?.[0];
  const firstValue = firstRelation?.toEntity?.valuesList?.[0];
  const avatar = firstValue?.text;
  if (typeof avatar === 'string') {
    return avatar;
  }
  return undefined;
};
const getEditorIdsFromSpace = space => {
  return (space.editorsList ?? []).map(e => e.memberSpaceId).filter(id => typeof id === 'string');
};
const getMemberIdsFromSpace = space => {
  return (space.membersList ?? []).map(m => m.memberSpaceId).filter(id => typeof id === 'string');
};
export const parseSpacesQueryResult = queryResult => {
  const data = [];
  const invalidSpaces = [];
  const spaces = queryResult.spaces ?? [];
  for (const space of spaces) {
    const rawSpace = {
      id: space.id,
      type: space.type,
      name: space.page?.name ?? undefined,
      avatar: getAvatarFromSpace(space),
      editorIds: getEditorIdsFromSpace(space),
      memberIds: getMemberIdsFromSpace(space)
    };
    const decodedSpace = decodeSpace(rawSpace);
    if (Either.isRight(decodedSpace)) {
      data.push(decodedSpace.right);
    } else {
      invalidSpaces.push(rawSpace);
    }
  }
  return {
    data,
    invalidSpaces
  };
};
const validateSpaceType = spaceType => {
  const result = EffectSchema.decodeUnknownEither(SpaceTypeSchema)(spaceType);
  if (Either.isLeft(result)) {
    throw new Error(`Invalid spaceType: ${spaceType}. Must be 'PERSONAL' or 'DAO'.`);
  }
  return result.right;
};
export const buildFilterString = filter => {
  const conditions = [];
  if (filter?.memberId) {
    // Validate memberId is a valid GeoId to prevent injection attacks
    const validatedMemberId = parseGeoId(filter.memberId);
    conditions.push(`members: {some: {memberSpaceId: {is: "${validatedMemberId}"}}}`);
  }
  if (filter?.editorId) {
    // Validate editorId is a valid GeoId to prevent injection attacks
    const validatedEditorId = parseGeoId(filter.editorId);
    conditions.push(`editors: {some: {memberSpaceId: {is: "${validatedEditorId}"}}}`);
  }
  if (filter?.spaceType) {
    // Validate spaceType at runtime to ensure it's a valid value
    const validatedSpaceType = validateSpaceType(filter.spaceType);
    conditions.push(`type: {is: ${validatedSpaceType}}`);
  }
  if (conditions.length === 0) {
    return undefined;
  }
  return `filter: {${conditions.join(', ')}}`;
};
export const buildSpacesQuery = filter => {
  const filterString = buildFilterString(filter);
  const filterClause = filterString ? `(${filterString})` : '';
  return `
query spaces {
  spaces${filterClause} {
    ${spaceFields}
  }
}
`;
};
export const findManyPublic = async params => {
  const filter = params?.filter;
  const memberId = filter?.memberId;
  const editorId = filter?.editorId;
  if (memberId && editorId) {
    throw new Error('Provide only one of memberId or editorId when calling findManyPublic().');
  }
  const endpoint = `${Config.getApiOrigin()}/v2/graphql`;
  const queryDocument = buildSpacesQuery(filter);
  const queryResult = await request(endpoint, queryDocument);
  return parseSpacesQueryResult(queryResult);
};
//# sourceMappingURL=find-many-public.js.map