import { BadRequestException, ForbiddenException } from '@nestjs/common';
import { PrismaClient } from '@prisma/client';

type Delegate = {
  findUnique(args: { where: any }): Promise<any>;
  findFirst(args: { where: any }): Promise<any>;
};

export async function findByIdAndUserId<T extends Delegate>(
  delegate: T,
  id: string,
  userId: string,
  resourceName: string,
) {
  const record = await delegate.findUnique({ where: { id } } as any);
  if (!record) {
    throw new BadRequestException(`${resourceName}不存在`);
  }
  if (record.userId !== userId) {
    throw new ForbiddenException(`无权访问该${resourceName}`);
  }
  return record;
}

export function ensureOwnership(
  record: any,
  userId: string,
  resourceName: string,
) {
  if (!record) {
    throw new BadRequestException(`${resourceName}不存在`);
  }
  if (record.userId !== userId) {
    throw new ForbiddenException(`无权访问该${resourceName}`);
  }
  return record;
}

export function sanitizeFilename(originalName: string): string {
  const ext = originalName.split('.').pop()?.toLowerCase() || '';
  const safeExt = ext.replace(/[^a-z0-9]/g, '');
  const randomName =
    Date.now().toString(36) + Math.random().toString(36).substring(2, 15);
  return `${randomName}.${safeExt}`;
}

export const ALLOWED_FILE_TYPES = [
  'application/pdf',
  'text/plain',
  'text/markdown',
  'text/csv',
  'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
  'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
  'image/png',
  'image/jpeg',
  'image/webp',
];

export const MAX_FILE_SIZE = 20 * 1024 * 1024;

export function validateFileUpload(
  mimeType: string,
  sizeBytes: number,
): void {
  if (!ALLOWED_FILE_TYPES.includes(mimeType)) {
    throw new BadRequestException(
      `不支持的文件类型: ${mimeType}，仅支持 PDF/Word/Excel/文本/图片`,
    );
  }
  if (sizeBytes > MAX_FILE_SIZE) {
    throw new BadRequestException(
      `文件大小不能超过 ${MAX_FILE_SIZE / 1024 / 1024}MB`,
    );
  }
}

export function maskSecret(secret: string): string {
  if (!secret || secret.length < 8) return '***';
  return secret.slice(0, 4) + '***' + secret.slice(-4);
}
