import { CogniteClient as CogniteClientV6 } from '@cognite/sdk-v6';
import { CogniteClient } from '@cognite/sdk';
import type { QueryRequest, Query } from './codegen';
import type { ModelNodeMap } from './schema';
import { RelationshipMap } from './schema';
/// <reference path='./codegen.d.ts'/>
import { generateQueryOp } from './codegen.esm.js';
import { FieldsSelection } from '@genql/runtime';

const getTypeKey = (typeName: string, version: number | string) =>
  `${typeName}_${version}`;

const getRelationshipKey = (
  typeName: string,
  attr: string,
  version: number | string
) => `${typeName}_${attr}_${version}`;

const CDF_ALPHA_VERSION_HEADERS = { 'cdf-version': 'alpha' };

export class FDMQueryClient {
  private _client: CogniteClient | CogniteClientV6;

  constructor(client: CogniteClient | CogniteClientV6) {
    this._client = client;
  }
  public runQuery = async <R extends QueryRequest>(
    query: R & { __name?: string }
  ) => {
    const response = await this._client.post<{
      data: FieldsSelection<Query, R>;
    }>(
      `/api/v1/projects/${PROJECT}/schema/api/${DM_NAME}/${DM_VERSION}/graphql`,
      { data: generateQueryOp(query) }
    );
    return response;
  };

  public async upsertNodes<T extends keyof ModelNodeMap>(
    key: T,
    items: ModelNodeMap[T][]
  ): Promise<ModelNodeMap[T][]> {
    const data = {
      items,
      spaceExternalId: DM_NAME,
      model: [DM_NAME, getTypeKey(key, DM_VERSION)],
      overwrite: true,
    };

    const res = await this._client.post<{ items: ModelNodeMap[T][] }>(
      `/api/v1/projects/${this._client.project}/datamodelstorage/nodes`,
      {
        data,
        headers: CDF_ALPHA_VERSION_HEADERS,
        responseType: 'json',
        withCredentials: true,
      }
    );

    return res.data.items;
  }

  public async upsertRelationships<
    I extends { startNode: string; endNode: string },
    K extends keyof typeof RelationshipMap
  >(
    type: K,
    property: keyof typeof RelationshipMap[K],
    items: I[]
  ): Promise<I[]> {
    const relationshipKey = getRelationshipKey(
      type,
      // @ts-ignore
      property,
      DM_VERSION
    );
    const data = {
      items: items.map((el) => ({
        ...el,
        type: relationshipKey,
        dummy: '',
        externalId: `${el.startNode}_${el.endNode}`,
      })),
      spaceExternalId: DM_NAME,
      model: [DM_NAME, relationshipKey],
      overwrite: true,
      autoCreateStartNodes: true,
      autoCreateEndNodes: true,
    };

    const res = await this._client.post<{ items: I[] }>(
      `/api/v1/projects/${this._client.project}/datamodelstorage/edges`,
      {
        data,
        headers: CDF_ALPHA_VERSION_HEADERS,
        responseType: 'json',
        withCredentials: true,
      }
    );

    return res.data.items;
  }
}

export const FDMQueryClientBuilder = {
  fromToken: (appId = 'FDMQueryClient') => {
    return new FDMQueryClient(
      new CogniteClientV6({
        appId,
        // @ts-ignore
        getToken: () => Promise.resolve(BEARER_TOKEN),
        project: PROJECT,
        baseUrl: `https://${CLUSTER}.cognitedata.com`,
      })
    );
  },
  fromClient: (client: CogniteClient) => {
    return new FDMQueryClient(client);
  },
};

/// <reference path='./codegen.d.ts'/>
export * from './codegen';
export * from './schema';

const BEARER_TOKEN="eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6IjJaUXBKM1VwYmpBWVhZR2FYRUpsOGxWMFRPSSIsImtpZCI6IjJaUXBKM1VwYmpBWVhZR2FYRUpsOGxWMFRPSSJ9.eyJhdWQiOiJodHRwczovL2JsdWVmaWVsZC5jb2duaXRlZGF0YS5jb20iLCJpc3MiOiJodHRwczovL3N0cy53aW5kb3dzLm5ldC9lNTQxNjI2Yi1kNTUyLTQ4OGItODY3NC0yNDk0N2MyYzM0MmUvIiwiaWF0IjoxNjYxOTUxNTAyLCJuYmYiOjE2NjE5NTE1MDIsImV4cCI6MTY2MTk1NzExMiwiYWNyIjoiMSIsImFpbyI6IkFRUUIrLzRUQUFBQXZaOHNHU2lTTExvelNONmlyeVNpNFpCb3Z6R2dyTWdZcWFoQjY3TmQrV3N1bWl2bEFTYWpqNWJybVkzSEI2eEZJeVNGMkhpbG1BZ3dZZDlpQWVaSzFPdzFQQ21EUmgrQVFndE03VnZYeWtiK3lZVVdLOFlYd3k1Vm5JelFza21iMVNlcmwwMFFGL1VJM2xjVHpFcmlSSVEwWHhNcjhaQjFmZHRpeWVjVzNjZ3BlYTNSVHdiQWhDTW02OUpOWEpnY1FpeSs3RE1JNWVPQlNROTc0QmU0SnVsQXpyWTRTeHczMEo1dThaRGJtTnB3TkNVM25OTENyejJFdFRNZFJmSVFoK3VxZ01JNkMya1hDR0kwZ3pYbG1ZWkRxRzdBTWdtY3g3emlOMzFGTWJYbUlTdnZhT2I0eFE3TkJSeVRPc0N3MTFYZXlyNUFGNzh3eFY3bm45RHZxZz09IiwiYW1yIjpbInB3ZCIsIm1mYSJdLCJhcHBpZCI6ImE3ODY5NDU1LTMyZjItNGEwNy1iNTY4LTg0ODViOWI4ODdmMCIsImFwcGlkYWNyIjoiMCIsImVtYWlsIjoiZGF2aWQubGl1QGNvZ25pdGVkYXRhLmNvbSIsImZhbWlseV9uYW1lIjoiZXZlciIsImdpdmVuX25hbWUiOiJncmVhdGVzdCIsImdyb3VwcyI6WyI1M2FjZGQ1Yi00OGMwLTQyMTEtYmVlNy1kODZiYjdiYjk0YTMiLCJmMjRiNmU4NC00YmNlLTRjNTAtOGEwZi03YjU1ODQ1MjNkZmIiLCJkZmQ3NzhjMi1hMDE2LTRhZGQtODExOS1jMDk1YjBmZGMxZTQiXSwiaWRwIjoiaHR0cHM6Ly9zdHMud2luZG93cy5uZXQvYTlhZTViNTQtMzYwMC00OTE3LWE5ZGMtMzAyMDcyMzM2MGIzLyIsImlwYWRkciI6Ijg0LjIxMC4xNTkuNTkiLCJuYW1lIjoieWEgYm9pIiwib2lkIjoiYWE0ZThmMmEtNTdhZC00NjNkLWI4ZTctNjQxNGNiNTE3Y2FiIiwicmgiOiIwLkFZSUFhMkpCNVZMVmkwaUdkQ1NVZkN3MEx2QjdCanFDU19aR2xQNUJIOUV5MlR1Q0FHby4iLCJzY3AiOiJJREVOVElUWSB1c2VyX2ltcGVyc29uYXRpb24iLCJzdWIiOiJjbGR4anBMV2R4WkpyLW9TUjBUNE1ldEhmT1g5RUJ0Z0g3bjR0N201em5jIiwidGlkIjoiZTU0MTYyNmItZDU1Mi00ODhiLTg2NzQtMjQ5NDdjMmMzNDJlIiwidW5pcXVlX25hbWUiOiJkYXZpZC5saXVAY29nbml0ZWRhdGEuY29tIiwidXRpIjoib2kwRk84TjBYMC1NUVo1NUNpTVpBQSIsInZlciI6IjEuMCJ9.ngHyZzAHFrgk9Uwy1ACunq5pT3LeNyp7mE5KUGIOrkImjApH2aumueTV1rBYqZpeTPIHgEIUgnqOfmhkvmJ2UuvgewVsSzTgIcr2pb6VJVEdwqztsYntn2OMtIIC4m4oQ65njSE4EukBGIZoZth9B-GfuXaWLx2WZKkGd9KTjvoX-xN95vlr9Wi1yGVLhF3gfhuSOOQzsajFHPPh5otdLYB5KE47-SrdnuEhEEL4BDDPaD8OKMH5XqtznagNN48aEgMnRuasDMbCFbxUPGyktKwfuwXIURZt9-ku0eBRkFFErS7NXSYrP4Y4EaU-GJCp6o3BciANbumTm0gaUL3XsA"
const CLUSTER="bluefield"
const PROJECT="david"
const TENANT="dlcognitetest.onmicrosoft.com"
const DM_NAME="moviedm"
const DM_VERSION="1"