import { Injectable } from '@nestjs/common';
import { InjectModel } from '@nestjs/mongoose';
import { Model, Types } from 'mongoose';
import {
  AiMusicArchive,
  AiMusicArchiveDocument,
  AiMusicArchiveType,
} from './schemas/ai-music-archive.schema';

@Injectable()
export class MediaRepository {
  constructor(
    @InjectModel(AiMusicArchive.name)
    private readonly aiMusicArchiveModel: Model<AiMusicArchiveDocument>,
  ) {}

  async createAiMusicArchiveItem(
    userId: string,
    payload: {
      type: AiMusicArchiveType;
      title: string;
      prompt: string;
      tag: string;
      audioUrl: string;
      storageKey?: string;
      durationSeconds?: number | null;
      mimeType?: string;
      sizeBytes?: number;
      waveformPeaks?: number[];
    },
  ): Promise<AiMusicArchiveDocument> {
    return this.aiMusicArchiveModel.create({
      ...payload,
      userId: new Types.ObjectId(userId),
      isDeleted: false,
    });
  }

  async findAiMusicArchiveItemsByUser(
    userId: string,
    skip: number,
    limit: number,
  ): Promise<AiMusicArchiveDocument[]> {
    return this.aiMusicArchiveModel
      .find({
        userId: new Types.ObjectId(userId),
        isDeleted: { $ne: true },
      })
      .sort({ createdAt: -1 })
      .skip(skip)
      .limit(limit)
      .exec();
  }

  async countAiMusicArchiveItemsByUser(userId: string): Promise<number> {
    return this.aiMusicArchiveModel
      .countDocuments({
        userId: new Types.ObjectId(userId),
        isDeleted: { $ne: true },
      })
      .exec();
  }

  async findAiMusicArchiveItemByUser(
    userId: string,
    itemId: string,
  ): Promise<AiMusicArchiveDocument | null> {
    if (!Types.ObjectId.isValid(itemId)) {
      return null;
    }

    return this.aiMusicArchiveModel
      .findOne({
        _id: new Types.ObjectId(itemId),
        userId: new Types.ObjectId(userId),
        isDeleted: { $ne: true },
      })
      .exec();
  }

  async updateAiMusicArchiveTitle(
    userId: string,
    itemId: string,
    title: string,
  ): Promise<AiMusicArchiveDocument | null> {
    if (!Types.ObjectId.isValid(itemId)) {
      return null;
    }

    return this.aiMusicArchiveModel
      .findOneAndUpdate(
        {
          _id: new Types.ObjectId(itemId),
          userId: new Types.ObjectId(userId),
          isDeleted: { $ne: true },
        },
        { title },
        { new: true },
      )
      .exec();
  }

  async softDeleteAiMusicArchiveItem(userId: string, itemId: string): Promise<boolean> {
    if (!Types.ObjectId.isValid(itemId)) {
      return false;
    }

    const updated = await this.aiMusicArchiveModel
      .findOneAndUpdate(
        {
          _id: new Types.ObjectId(itemId),
          userId: new Types.ObjectId(userId),
          isDeleted: { $ne: true },
        },
        { isDeleted: true },
        { new: false },
      )
      .exec();

    return !!updated;
  }
}
