/**
 * @file stampAnnotations.ts - Utilities for creating and adding custom stamp annotations to documents in the Syncfusion PDF viewer.
 * Includes predefined stamp images and a dynamically generated signature stamp rendered in cursive font.
 * Stamp annotations are added at the current page and sized by dividing their native image dimensions by a constant divisor for consistent display.
 */

import { StaticCanvas, Text, Rect } from 'fabric';
import { CUSTOM_STAMP_ANNOTATION_SIZE_DIVISOR } from '../constants.ts';
import type { RefObject } from 'react';
import type {
  CustomStampSettings,
  PdfViewerComponent,
} from '@syncfusion/ej2-react-pdfviewer';

// Import static assets for custom stamps (inlined as base64 data URIs by Vite)
import {
  // @ts-expect-error vite-imagetools OutputMetadata
  src as unreadableStampSrc,
} from '../assets/stamps/unreadable.png?inline';
import {
  // @ts-expect-error vite-imagetools OutputMetadata
  src as checkCopyStampSrc,
} from '../assets/stamps/check_copy.png?inline';
import {
  // @ts-expect-error vite-imagetools OutputMetadata
  src as receiptOnlyStampSrc,
} from '../assets/stamps/receipt_only.png?inline';
import {
  // @ts-expect-error vite-imagetools OutputMetadata
  src as noReturnAddressStampSrc,
} from '../assets/stamps/no_return_address.png?inline';
import {
  // @ts-expect-error vite-imagetools OutputMetadata
  src as blankPageStampSrc,
} from '../assets/stamps/blank_page.png?inline';

/**
 * Represents a custom stamp annotation with its image data and dimensions.
 */
export type CustomStampAnnotation = {
  /** Base64 data URI of the stamp image */
  asset: string;

  /** Native width of the stamp image in pixels */
  width: number;

  /** Native height of the stamp image in pixels */
  height: number;
};

/**
 * Predefined custom stamp annotations with their inlined image assets and native dimensions.
 */
export const customStampAnnotations = {
  Unreadable: {
    asset: unreadableStampSrc,
    width: 646,
    height: 143,
  } as CustomStampAnnotation,
  CheckCopy: {
    asset: checkCopyStampSrc,
    width: 612,
    height: 145,
  } as CustomStampAnnotation,
  ReceiptOnly: {
    asset: receiptOnlyStampSrc,
    width: 676,
    height: 145,
  } as CustomStampAnnotation,
  NoReturnAddress: {
    asset: noReturnAddressStampSrc,
    width: 1017,
    height: 145,
  } as CustomStampAnnotation,
  BlankPage: {
    asset: blankPageStampSrc,
    width: 605,
    height: 145,
  } as CustomStampAnnotation,
};

/**
 * Generates an image in cursive font from the current user's username to serve as a stamp annotation for their signature in the Syncfusion PDF viewer.
 *
 * @param username Username of current user
 * @returns Custom signature stamp annotation
 */
export async function generateSignatureAnnotation(
  username: string
): Promise<CustomStampAnnotation> {
  // Dancing Script font
  const fontFamily = 'Dancing Script';
  const fontSize = 100;
  const fontWeight = 400;
  const color = 'black';

  // Make sure font is loaded
  await document.fonts.load(`${fontWeight} ${fontSize}px "${fontFamily}"`);

  // Create a basic canvas
  const canvas = new StaticCanvas(undefined, {
    width: 1,
    height: 1,
  });

  // Create a text object
  const textObj = new Text(username, {
    fontFamily,
    fontSize,
    fontWeight,
    fill: color,
  });

  // Set canvas dimensions according to text size
  canvas.width = textObj.getScaledWidth();
  canvas.height = textObj.getScaledHeight();

  // Paint backing rectangle
  canvas.add(
    new Rect({
      width: canvas.width,
      height: canvas.height,
      fill: 'transparent',
      selectable: false,
    })
  );

  // Paint text
  canvas.add(textObj);

  return {
    asset: canvas.toDataURL(),
    width: canvas.width,
    height: canvas.height,
  };
}

/**
 * Adds a custom stamp annotation to the current page in the Syncfusion PDF Viewer.
 *
 * @param pdfViewerRef RefObject of Syncfusion PDF Viewer component
 * @param stampName Name of custom stamp to be added
 * @param username Username of current user (stamp annotation author)
 */
export const addCustomStampAnnotation = (
  pdfViewerRef: RefObject<PdfViewerComponent>,
  stampName: keyof typeof customStampAnnotations,
  username: string
) => {
  pdfViewerRef.current?.annotation.setAnnotationMode('None');
  pdfViewerRef.current?.annotation.addAnnotation('Stamp', {
    width: Math.ceil(
      customStampAnnotations[stampName].width /
        CUSTOM_STAMP_ANNOTATION_SIZE_DIVISOR
    ),
    height: Math.ceil(
      customStampAnnotations[stampName].height /
        CUSTOM_STAMP_ANNOTATION_SIZE_DIVISOR
    ),
    author: username as string,
    isLock: false,
    pageNumber: pdfViewerRef.current?.currentPageNumber,
    customStamps: [
      {
        customStampName: stampName,
        customStampImageSource: customStampAnnotations[stampName].asset,
      },
    ],
  } as CustomStampSettings);
};

/**
 * Adds the signature stamp annotation to the current page in the Syncfusion PDF Viewer.
 *
 * @param pdfViewerRef RefObject of Syncfusion PDF Viewer component
 * @param signatureAnnotation Signature annotation object
 * @param username Username of current user (stamp annotation author)
 */
export const addSignatureAnnotation = (
  pdfViewerRef: RefObject<PdfViewerComponent>,
  signatureAnnotation: CustomStampAnnotation,
  username: string
) => {
  if (signatureAnnotation) {
    pdfViewerRef.current?.annotation.setAnnotationMode('None');
    pdfViewerRef.current?.annotation.addAnnotation('Stamp', {
      width: Math.ceil(
        signatureAnnotation.width / CUSTOM_STAMP_ANNOTATION_SIZE_DIVISOR
      ),
      height: Math.ceil(
        signatureAnnotation.height / CUSTOM_STAMP_ANNOTATION_SIZE_DIVISOR
      ),
      author: username as string,
      isLock: false,
      pageNumber: pdfViewerRef.current?.currentPageNumber,
      customStamps: [
        {
          customStampName: 'Signature',
          customStampImageSource: signatureAnnotation.asset,
        },
      ],
    } as CustomStampSettings);
  }
};
