import { Injectable, Logger, NotFoundException } from '@nestjs/common';
import { customAlphabet } from 'nanoid-cjs';
import { db } from '@nice/common';
import { ShareCode, GenerateShareCodeResponse } from './types';
import { Cron, CronExpression } from '@nestjs/schedule';
import { ResourceService } from '@server/models/resource/resource.service';

@Injectable()
export class ShareCodeService {
  private readonly logger = new Logger(ShareCodeService.name);
  // 生成8位分享码，使用易读的字符
  private readonly generateCode = customAlphabet(
    '23456789ABCDEFGHJKLMNPQRSTUVWXYZ',
    8,
  );

  constructor(private readonly resourceService: ResourceService) {}

  async generateShareCode(
    fileId: string,
    fileName?: string,
  ): Promise<GenerateShareCodeResponse> {
    try {
      // 检查文件是否存在
      const resource = await this.resourceService.findUnique({
        where: { fileId },
      });
      console.log('完整 fileId:', fileId); // 确保与前端一致

      if (!resource) {
        throw new NotFoundException('文件不存在');
      }

      // 生成分享码
      const code = this.generateCode();
      const expiresAt = new Date(Date.now() + 24 * 60 * 60 * 1000); // 24小时后过期

      // 查找是否已有分享码记录
      const existingShareCode = await db.shareCode.findUnique({
        where: { fileId },
      });

      if (existingShareCode) {
        // 更新现有记录，但保留原有文件名
        await db.shareCode.update({
          where: { fileId },
          data: {
            code,
            expiresAt,
            isUsed: false,
            // 只在没有现有文件名且提供了新文件名时才更新文件名
            ...(fileName && !existingShareCode.fileName ? { fileName } : {}),
          },
        });
      } else {
        // 创建新记录
        await db.shareCode.create({
          data: {
            code,
            fileId,
            expiresAt,
            isUsed: false,
            fileName: fileName || null,
          },
        });
      }
      this.logger.log(`Generated share code ${code} for file ${fileId}`);
      return {
        code,
        expiresAt,
      };
    } catch (error) {
      this.logger.error('Failed to generate share code', error);
      throw error;
    }
  }

  async validateAndUseCode(code: string): Promise<ShareCode | null> {
    try {
      console.log(`尝试验证分享码: ${code}`);

      // 查找有效的分享码
      const shareCode = await db.shareCode.findFirst({
        where: {
          code,
          isUsed: false,
          expiresAt: { gt: new Date() },
        },
      });

      console.log('查询结果:', shareCode);

      if (!shareCode) {
        console.log('分享码无效或已过期');
        return null;
      }

      // 标记分享码为已使用
      // await db.shareCode.update({
      //   where: { id: shareCode.id },
      //   data: { isUsed: true },
      // });

      // 记录使用日志
      this.logger.log(`Share code ${code} used for file ${shareCode.fileId}`);

      // 返回完整的分享码信息，包括文件名
      return shareCode;
    } catch (error) {
      this.logger.error('Failed to validate share code', error);
      return null;
    }
  }

  // 每天清理过期的分享码
  @Cron(CronExpression.EVERY_DAY_AT_MIDNIGHT)
  async cleanupExpiredShareCodes() {
    try {
      const result = await db.shareCode.deleteMany({
        where: {
          OR: [{ expiresAt: { lt: new Date() } }, { isUsed: true }],
        },
      });

      this.logger.log(`Cleaned up ${result.count} expired share codes`);
    } catch (error) {
      this.logger.error('Failed to cleanup expired share codes', error);
    }
  }

  // 获取分享码信息
  async getShareCodeInfo(code: string): Promise<ShareCode | null> {
    try {
      return await db.shareCode.findFirst({
        where: { code },
      });
    } catch (error) {
      this.logger.error('Failed to get share code info', error);
      return null;
    }
  }

  // 检查文件是否已经生成过分享码
  async hasActiveShareCode(fileId: string): Promise<boolean> {
    try {
      const activeCode = await db.shareCode.findFirst({
        where: {
          fileId,
          isUsed: false,
          expiresAt: { gt: new Date() },
        },
      });

      return !!activeCode;
    } catch (error) {
      this.logger.error('Failed to check active share code', error);
      return false;
    }
  }

  // 获取文件的所有分享记录
  async getFileShareHistory(fileId: string) {
    try {
      return await db.shareCode.findMany({
        where: { fileId },
        orderBy: { createdAt: 'desc' },
      });
    } catch (error) {
      this.logger.error('Failed to get file share history', error);
      return [];
    }
  }
}
