import { Graph } from '@graphprotocol/grc-20';
import { Constants, Utils } from '@graphprotocol/hypergraph';
import * as Either from 'effect/Either';
import * as Option from 'effect/Option';
import * as Schema from 'effect/Schema';
import * as SchemaAST from 'effect/SchemaAST';
import { request } from 'graphql-request';
import { buildRelationsSelection } from '../utils/relation-query-helpers.js';
import { normalizeSpaceIds } from './internal/normalize-space-ids.js';
const buildEntityQuery = (relationInfoLevel1, includeSpaceIds) => {
  const relationsSelection = buildRelationsSelection(relationInfoLevel1, 'single');
  const relationsSelectionBlock = relationsSelection ? `\n    ${relationsSelection}\n` : '';
  const spaceIdsSelection = includeSpaceIds ? '\n    spaceIds' : '';
  return `
query entity($id: UUID!, $spaceId: UUID!) {
  entity(
    id: $id,
  ) {
    id
    name${spaceIdsSelection}
    valuesList(filter: {spaceId: {is: $spaceId}}) {
      propertyId
      string
      boolean
      number
      time
      point
    }${relationsSelectionBlock}
  }
}
`;
};
const parseResult = (queryData, type, relationInfoLevel1, options) => {
  const includeSpaceIds = options?.includeSpaceIds;
  if (!queryData.entity) {
    return {
      entity: null,
      invalidEntity: null,
      invalidRelationEntities: []
    };
  }
  const schemaWithId = Utils.addIdSchemaField(type);
  const decode = Schema.decodeUnknownEither(schemaWithId);
  const queryEntity = queryData.entity;
  let rawEntity = {
    id: queryEntity.id
  };
  const ast = type.ast;
  for (const prop of ast.propertySignatures) {
    const propType = prop.isOptional && SchemaAST.isUnion(prop.type) ? prop.type.types.find(member => !SchemaAST.isUndefinedKeyword(member)) ?? prop.type : prop.type;
    const result = SchemaAST.getAnnotation(Constants.PropertyIdSymbol)(propType);
    if (Option.isSome(result)) {
      const value = queryEntity.valuesList.find(a => a.propertyId === result.value);
      if (value) {
        const rawValue = Utils.convertPropertyValue(value, propType);
        if (rawValue) {
          rawEntity[String(prop.name)] = rawValue;
        }
      }
    }
  }
  const {
    rawEntity: relationEntities,
    invalidRelations
  } = Utils.convertRelations(queryEntity, ast, relationInfoLevel1);
  // @ts-expect-error
  rawEntity = {
    ...rawEntity,
    ...relationEntities
  };
  const decodeResult = decode({
    ...rawEntity,
    __deleted: false
  });
  if (Either.isRight(decodeResult)) {
    const enrichedEntity = (() => {
      if (!includeSpaceIds) {
        return decodeResult.right;
      }
      return {
        ...decodeResult.right,
        spaceIds: normalizeSpaceIds(queryEntity.spaceIds)
      };
    })();
    return {
      entity: enrichedEntity,
      invalidEntity: null,
      invalidRelationEntities: invalidRelations
    };
  }
  const invalidRawEntity = includeSpaceIds ? {
    ...rawEntity,
    spaceIds: normalizeSpaceIds(queryEntity.spaceIds)
  } : rawEntity;
  return {
    entity: null,
    invalidEntity: {
      raw: invalidRawEntity,
      error: decodeResult.left
    },
    invalidRelationEntities: invalidRelations
  };
};
export const findOnePublic = async (type, params) => {
  const {
    id,
    space,
    include,
    includeSpaceIds: includeSpaceIdsParam,
    logInvalidResults = true
  } = params;
  const includeSpaceIds = includeSpaceIdsParam ?? false;
  // constructing the relation type ids for the query
  const relationTypeIds = Utils.getRelationTypeIds(type, include);
  const queryDocument = buildEntityQuery(relationTypeIds, includeSpaceIds);
  const result = await request(`${Graph.TESTNET_API_ORIGIN}/graphql`, queryDocument, {
    id,
    spaceId: space
  });
  const parsed = parseResult(result, type, relationTypeIds, includeSpaceIdsParam === undefined ? undefined : {
    includeSpaceIds: includeSpaceIdsParam
  });
  if (logInvalidResults) {
    if (parsed.invalidEntity) {
      console.warn('Entity decoding failed', parsed.invalidEntity);
    }
    if (parsed.invalidRelationEntities.length > 0) {
      console.warn('Relation entities where decoding failed were dropped', parsed.invalidRelationEntities);
    }
  }
  return parsed;
};
//# sourceMappingURL=find-one-public.js.map