import { prisma } from "../database";
import { Recording, Prisma } from "@prisma/client";
import { writeFile, unlink } from "fs/promises";
import { join } from "path";
import { cache } from "../cache";
import { logger } from "../utils/logger";
import { S3Client, DeleteObjectCommand } from "@aws-sdk/client-s3";

export interface CreateRecordingData {
  title: string;
  audioUrl: string;
  duration: number;
  fileSize: number;
  mimeType: string;
  userId: string;
}

export interface UpdateRecordingData {
  title?: string;
  duration?: number;
}

export interface RecordingWithUser {
  id: string;
  title: string;
  audioUrl: string;
  duration: number;
  fileSize: number;
  mimeType: string;
  createdAt: Date;
  user: {
    id: string;
    name: string | null;
    email: string | null;
  };
}

// S3 删除工具函数
async function deleteS3File(audioUrl: string) {
  try {
    const s3 = new S3Client({
      region: process.env.AWS_REGION || "us-east-1",
      credentials: {
        accessKeyId: process.env.AWS_ACCESS_KEY_ID!,
        secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY!,
      },
    });
    const url = new URL(audioUrl);
    const bucket = url.hostname.split(".")[0];
    const key = url.pathname.slice(1); // 去掉开头的 /
    await s3.send(new DeleteObjectCommand({ Bucket: bucket, Key: key }));
    console.log(`S3 文件删除成功: ${bucket}/${key}`);
  } catch (err) {
    console.warn("S3 文件删除失败（忽略）:", err);
  }
}

export class RecordingService {
  /**
   * 创建新录音
   */
  static async createRecording(data: CreateRecordingData): Promise<Recording> {
    const startTime = Date.now();

    try {
      const recording = await prisma.recording.create({
        data,
      });

      // 清除相关缓存
      cache.delete(`recordings:user:${data.userId}`);
      cache.delete(`stats:user:${data.userId}`);

      // 清除可能的缓存变体
      cache.delete(`recordings:user:${data.userId}:0:20:{"createdAt":"desc"}`);
      cache.delete(`recordings:user:${data.userId}:0:50:{"createdAt":"desc"}`);

      logger.logDbOperation("create", "recording", Date.now() - startTime);
      logger.logUserAction(data.userId, "create_recording", {
        recordingId: recording.id,
      });

      return recording;
    } catch (error) {
      logger.error(
        "Failed to create recording",
        { userId: data.userId },
        error as Error
      );
      throw error;
    }
  }

  /**
   * 根据ID获取录音
   */
  static async getRecordingById(id: string): Promise<Recording | null> {
    const cacheKey = `recording:${id}`;
    const cached = cache.get<Recording>(cacheKey);

    if (cached) {
      return cached;
    }

    const startTime = Date.now();

    try {
      const recording = await prisma.recording.findUnique({
        where: { id },
      });

      if (recording) {
        cache.set(cacheKey, recording, 10 * 60 * 1000); // 缓存10分钟
      }

      logger.logDbOperation("findUnique", "recording", Date.now() - startTime);
      return recording;
    } catch (error) {
      logger.error("Failed to get recording by ID", { id }, error as Error);
      throw error;
    }
  }

  /**
   * 根据用户ID获取录音列表
   */
  static async getRecordingsByUserId(
    userId: string,
    options?: {
      skip?: number;
      take?: number;
      orderBy?: Prisma.RecordingOrderByWithRelationInput;
    }
  ): Promise<RecordingWithUser[]> {
    const {
      skip = 0,
      take = 50,
      orderBy = { createdAt: "desc" },
    } = options || {};
    const cacheKey = `recordings:user:${userId}:${skip}:${take}:${JSON.stringify(
      orderBy
    )}`;

    const cached = cache.get<RecordingWithUser[]>(cacheKey);
    if (cached) {
      return cached;
    }

    const startTime = Date.now();

    try {
      const recordings = await prisma.recording.findMany({
        where: { userId },
        skip,
        take,
        orderBy,
        include: {
          user: {
            select: {
              id: true,
              name: true,
              email: true,
            },
          },
        },
      });

      cache.set(cacheKey, recordings, 5 * 60 * 1000); // 缓存5分钟
      logger.logDbOperation("findMany", "recording", Date.now() - startTime);

      return recordings;
    } catch (error) {
      logger.error(
        "Failed to get recordings by user ID",
        { userId },
        error as Error
      );
      throw error;
    }
  }

  /**
   * 更新录音信息
   */
  static async updateRecording(
    id: string,
    userId: string,
    data: UpdateRecordingData
  ): Promise<Recording> {
    const startTime = Date.now();

    console.log(
      `RecordingService.updateRecording - 开始更新录音: ${id}, 用户: ${userId}, 数据:`,
      data
    );

    try {
      // 验证录音所有权
      const recording = await prisma.recording.findFirst({
        where: { id, userId },
      });

      console.log(
        `RecordingService.updateRecording - 查找录音结果:`,
        recording ? "找到" : "未找到"
      );

      if (!recording) {
        throw new Error("录音不存在或无权限");
      }

      console.log(
        `RecordingService.updateRecording - 开始更新数据库, 当前标题: "${recording.title}"`
      );

      const updatedRecording = await prisma.recording.update({
        where: { id },
        data,
      });

      console.log(
        `RecordingService.updateRecording - 数据库更新成功, 新标题: "${updatedRecording.title}"`
      );

      // 清除相关缓存
      cache.delete(`recording:${id}`);
      cache.delete(`recordings:user:${userId}`);

      // 清除可能的缓存变体
      cache.delete(`recordings:user:${userId}:0:20:{"createdAt":"desc"}`);
      cache.delete(`recordings:user:${userId}:0:50:{"createdAt":"desc"}`);

      // 清除所有可能的录音列表缓存
      const commonSkipValues = [0, 20, 50, 100];
      const commonTakeValues = [20, 50, 100];
      const commonOrderBy = ['{"createdAt":"desc"}', '{"createdAt":"asc"}'];

      for (const skip of commonSkipValues) {
        for (const take of commonTakeValues) {
          for (const orderBy of commonOrderBy) {
            cache.delete(
              `recordings:user:${userId}:${skip}:${take}:${orderBy}`
            );
          }
        }
      }

      logger.logDbOperation("update", "recording", Date.now() - startTime);
      logger.logUserAction(userId, "update_recording", {
        recordingId: id,
        data,
      });

      return updatedRecording;
    } catch (error) {
      console.error(`RecordingService.updateRecording - 更新失败:`, error);
      logger.error(
        "Failed to update recording",
        { id, userId },
        error as Error
      );
      throw error;
    }
  }

  /**
   * 删除录音
   */
  static async deleteRecording(id: string, userId: string): Promise<void> {
    const startTime = Date.now();

    try {
      console.log(
        `RecordingService: Attempting to delete recording ${id} for user ${userId}`
      );

      // 验证录音所有权
      const recording = await prisma.recording.findFirst({
        where: { id, userId },
      });

      console.log(
        `RecordingService: Found recording:`,
        recording ? "Yes" : "No"
      );

      if (!recording) {
        // 检查录音是否存在，但属于其他用户
        const otherRecording = await prisma.recording.findUnique({
          where: { id },
        });

        if (otherRecording) {
          console.log(
            `RecordingService: Recording exists but belongs to user ${otherRecording.userId}, not ${userId}`
          );
          throw new Error("录音不存在或无权限");
        } else {
          console.log(`RecordingService: Recording ${id} does not exist`);
          throw new Error("录音不存在");
        }
      }

      // 先删除 S3 文件
      await deleteS3File(recording.audioUrl);

      console.log(`RecordingService: Deleting recording from database`);

      // 删除数据库记录
      await prisma.recording.delete({
        where: { id },
      });

      // 清除相关缓存 - 更彻底的清除
      cache.delete(`recording:${id}`);
      cache.delete(`recordings:user:${userId}`);
      cache.delete(`stats:user:${userId}`);

      // 清除可能的缓存变体
      cache.delete(`recordings:user:${userId}:0:20:{"createdAt":"desc"}`);
      cache.delete(`recordings:user:${userId}:0:50:{"createdAt":"desc"}`);

      console.log(`RecordingService: Cache cleared`);

      logger.logDbOperation("delete", "recording", Date.now() - startTime);
      logger.logUserAction(userId, "delete_recording", { recordingId: id });

      console.log(`RecordingService: Recording ${id} deleted successfully`);
    } catch (error) {
      console.error(
        `RecordingService: Failed to delete recording ${id}:`,
        error
      );
      logger.error(
        "Failed to delete recording",
        { id, userId },
        error as Error
      );
      throw error;
    }
  }

  /**
   * 保存录音文件
   */
  static async saveRecordingFile(
    file: Buffer,
    filename: string
  ): Promise<string> {
    const startTime = Date.now();

    try {
      // 验证文件大小 (50MB 限制)
      const maxSize = 50 * 1024 * 1024;
      if (file.length > maxSize) {
        throw new Error("文件大小不能超过 50MB");
      }

      // 验证文件名格式
      const filenameRegex = /^recording-\d+\.webm$/;
      if (!filenameRegex.test(filename)) {
        throw new Error("文件名格式不正确");
      }

      // 验证文件内容类型 - 更宽松的 WebM 验证
      if (file.length < 4) {
        throw new Error("文件太小，无法验证格式");
      }

      const webmHeader = file.slice(0, 4);
      const webmSignature = Buffer.from([0x1a, 0x45, 0xdf, 0xa3]);

      // 检查是否为 WebM 格式，但也允许其他音频格式
      const isValidWebM = webmHeader.equals(webmSignature);
      const hasAudioExtension =
        filename.toLowerCase().endsWith(".webm") ||
        filename.toLowerCase().endsWith(".mp3") ||
        filename.toLowerCase().endsWith(".wav");

      if (!isValidWebM && !hasAudioExtension) {
        logger.warn("File format validation failed", {
          filename,
          header: webmHeader.toString("hex"),
          expected: webmSignature.toString("hex"),
        });
        // 不抛出错误，允许上传，但记录警告
      }

      const uploadDir = join(process.cwd(), "public", "recordings");
      const filePath = join(uploadDir, filename);

      await writeFile(filePath, file);

      logger.info("Recording file saved", {
        filename,
        size: file.length,
        duration: Date.now() - startTime,
      });

      return `/recordings/${filename}`;
    } catch (error) {
      logger.error(
        "Failed to save recording file",
        { filename },
        error as Error
      );
      throw new Error("保存录音文件失败");
    }
  }

  /**
   * 获取用户录音统计
   */
  static async getUserRecordingStats(userId: string): Promise<{
    totalRecordings: number;
    totalDuration: number;
    totalFileSize: number;
  }> {
    const cacheKey = `stats:user:${userId}`;
    const cached = cache.get<{
      totalRecordings: number;
      totalDuration: number;
      totalFileSize: number;
    }>(cacheKey);

    if (cached) {
      return cached;
    }

    const startTime = Date.now();

    try {
      const stats = await prisma.recording.aggregate({
        where: { userId },
        _count: {
          id: true,
        },
        _sum: {
          duration: true,
          fileSize: true,
        },
      });

      const result = {
        totalRecordings: stats._count.id,
        totalDuration: stats._sum.duration || 0,
        totalFileSize: stats._sum.fileSize || 0,
      };

      cache.set(cacheKey, result, 10 * 60 * 1000); // 缓存10分钟
      logger.logDbOperation("aggregate", "recording", Date.now() - startTime);

      return result;
    } catch (error) {
      logger.error(
        "Failed to get user recording stats",
        { userId },
        error as Error
      );
      throw error;
    }
  }

  /**
   * 批量删除用户录音
   */
  static async deleteUserRecordings(userId: string): Promise<void> {
    const startTime = Date.now();

    try {
      const recordings = await prisma.recording.findMany({
        where: { userId },
      });

      // 删除所有录音文件
      for (const recording of recordings) {
        try {
          const filePath = join(process.cwd(), "public", recording.audioUrl);
          await unlink(filePath);
        } catch {
          // 忽略文件删除错误
          logger.warn("Failed to delete recording file during bulk delete", {
            filePath: recording.audioUrl,
          });
        }
      }

      // 删除数据库记录
      await prisma.recording.deleteMany({
        where: { userId },
      });

      // 清除相关缓存
      cache.delete(`recordings:user:${userId}`);
      cache.delete(`stats:user:${userId}`);

      logger.logDbOperation("deleteMany", "recording", Date.now() - startTime);
      logger.logUserAction(userId, "delete_all_recordings", {
        count: recordings.length,
      });
    } catch (error) {
      logger.error(
        "Failed to delete user recordings",
        { userId },
        error as Error
      );
      throw error;
    }
  }
}
