import { PDFDocument } from '@pdfme/pdf-lib';
import { sha256 } from '@/features/foundation/storage/server/checksum';
import {
  DOCUMENT_LIBRARY_BRANDS,
  DOCUMENT_LIBRARY_LANGUAGES,
  DOCUMENT_LIBRARY_PRODUCT_TYPES,
  DOCUMENT_LIBRARY_TYPES,
  type DocumentLibraryBrand,
  type DocumentLibraryLanguage,
  type DocumentLibraryProductType,
  type DocumentLibraryType,
  type DocumentLibraryVersionStatus
} from '../types';

export const MAX_DOCUMENT_LIBRARY_FILE_SIZE = 20 * 1024 * 1024;

const ALLOWED_STATUS_TRANSITIONS: Record<
  DocumentLibraryVersionStatus,
  DocumentLibraryVersionStatus[]
> = {
  draft: ['published', 'archived'],
  published: ['active', 'archived'],
  active: [],
  archived: []
};

export function normalizeDocumentLibraryCode(value: string) {
  return value.trim().toUpperCase().replace(/[^A-Z0-9]+/g, '_').replace(/^_+|_+$/g, '');
}

export function assertSupportedDocumentType(value: string): asserts value is DocumentLibraryType {
  if (!DOCUMENT_LIBRARY_TYPES.includes(value as DocumentLibraryType)) {
    throw new Error(`Unsupported document type: ${value}`);
  }
}

export function assertSupportedBrand(value: string): asserts value is DocumentLibraryBrand {
  if (!DOCUMENT_LIBRARY_BRANDS.includes(value as DocumentLibraryBrand)) {
    throw new Error(`Unsupported brand: ${value}`);
  }
}

export function assertSupportedLanguage(
  value: string
): asserts value is DocumentLibraryLanguage {
  if (!DOCUMENT_LIBRARY_LANGUAGES.includes(value as DocumentLibraryLanguage)) {
    throw new Error(`Unsupported language: ${value}`);
  }
}

export function assertSupportedProductType(
  value: string
): asserts value is DocumentLibraryProductType {
  if (!DOCUMENT_LIBRARY_PRODUCT_TYPES.includes(value as DocumentLibraryProductType)) {
    throw new Error(`Unsupported product type: ${value}`);
  }
}

export function assertLifecycleTransition(
  currentStatus: DocumentLibraryVersionStatus,
  nextStatus: DocumentLibraryVersionStatus
) {
  if (currentStatus === nextStatus) {
    return;
  }

  if (!ALLOWED_STATUS_TRANSITIONS[currentStatus].includes(nextStatus)) {
    throw new Error(`Invalid lifecycle transition: ${currentStatus} -> ${nextStatus}`);
  }
}

export function assertCanDeleteDraftVersion(status: DocumentLibraryVersionStatus, isActive: boolean) {
  if (status !== 'draft' || isActive) {
    throw new Error('Only inactive draft versions can be deleted.');
  }
}

export async function parsePdfUpload(args: {
  fileName: string;
  mimeType: string;
  size: number;
  buffer: Buffer;
}) {
  if (args.mimeType !== 'application/pdf') {
    throw new Error('Only PDF uploads are supported.');
  }

  if (args.size <= 0) {
    throw new Error('Uploaded file is empty.');
  }

  if (args.size > MAX_DOCUMENT_LIBRARY_FILE_SIZE) {
    throw new Error('Uploaded PDF exceeds the size limit.');
  }

  const pdf = await PDFDocument.load(args.buffer);
  const pageCount = pdf.getPageCount();

  if (pageCount <= 0) {
    throw new Error('Uploaded PDF must contain at least one page.');
  }

  return {
    contentType: 'application/pdf' as const,
    checksum: sha256(args.buffer),
    fileSize: args.size,
    fileName: args.fileName,
    pageCount
  };
}
