/* eslint-disable @typescript-eslint/no-unused-vars */
import type { IDAgent } from './agent/index.js';
import type { DecodedVcJwt, Signer } from './credentials/credential.js';
import type { DecodedVpJwt, JwtHeaderParams } from './credentials/presentation.js';
import type { JwtDecodedVerifiablePresentation, PresentationSubmission } from '@sphereon/ssi-types';
import type { EvaluationResults, PresentationResult, Validated as PexValidated } from '@sphereon/pex';
import type { PresentationDefinitionV2 } from './credentials/presentation.js';
import { Convert } from './common/index.js';
import { Ed25519 } from './crypto/index.js';
import { createJwt, decodeJwt, SignOptions, VerifiableCredential } from './credentials/credential.js';
import { PresentationExchange } from './credentials/presentation.js';

/**
 * The VC API is used to issue, present and verify VCs
 *
 * @beta
 */
export class VcApi {
  private agent: IDAgent;
  private connectedDid: string;

  constructor(options: {
    agent: IDAgent,
    connectedDid: string,
  }) {
    this.agent = options.agent;
    this.connectedDid = options.connectedDid;
  }

  async createCredential(
    issuer: string,
    subject: string,
    data: any,
    type?: string,
  ): Promise<VerifiableCredential> {
    const vc = VerifiableCredential.create({
      issuer,
      subject,
      data,
      type,
    });
    return vc;
  }

  async signCredential(
    vc: VerifiableCredential,
    signOptions: SignOptions
  ): Promise<any> {
    return await vc.sign(signOptions);
  }

  async createJWT(
    payload: any,
    signOptions: SignOptions
  ): Promise<any> {
    return await createJwt(payload, signOptions);
  }

  async decodeJWT(
    jwt: string
  ): Promise<DecodedVcJwt> {
    return decodeJwt(jwt);
  }

  async parseJWT(
    jwt: string
  ): Promise<VerifiableCredential> {
    return await VerifiableCredential.parseJwt(jwt);
  }

  async verifyJWT(
    jwt: string
  ): Promise<boolean> {
    try {
      VerifiableCredential.verify(jwt);
      return true;
    } catch(e) {
      console.log('verifyJWT error', e);
      return false;
    }
  }

  async createPresentation(
    vcJwts: string[],
    presentationDefinition: PresentationDefinitionV2
  ): Promise<PresentationResult> {
    return PresentationExchange.createPresentationFromCredentials(vcJwts, presentationDefinition);
  }

  async satisfiesPresentation(
    vcJwts: string[],
    presentationDefinition: PresentationDefinitionV2
  ): Promise<boolean> {
    try {
      PresentationExchange.validateDefinition(presentationDefinition);
      PresentationExchange.satisfiesPresentationDefinition(vcJwts, presentationDefinition);
      return true;
    } catch (err) {
      return false;
    }
  }

  async decodePresentation(
    jwt: string
  ): Promise<DecodedVpJwt> {
    const [encodedHeader, encodedPayload, encodedSignature] = jwt.split('.');
    return {
      header    : Convert.base64Url(encodedHeader).toObject() as JwtHeaderParams,
      payload   : Convert.base64Url(encodedPayload).toObject() as JwtDecodedVerifiablePresentation,
      signature : encodedSignature
    };
  }

  async evaluatePresentation(
    presentationDefinition: PresentationDefinitionV2,
    presentationResult: any,
  ): Promise<EvaluationResults> {
    return PresentationExchange.evaluatePresentation(presentationDefinition,  presentationResult.presentation );
  }

  async validateSubmission(
    presentationSubmission: PresentationSubmission,
  ): Promise<any> {
    return PresentationExchange.validateSubmission(presentationSubmission);
  }

  EdDsaSigner(
    privateKey: Uint8Array
  ): Signer {
    return async (data: Uint8Array): Promise<Uint8Array> => {
      const signature = await Ed25519.sign({ data, key: privateKey});
      return signature;
    };
  }

}