import { Injectable, NotFoundException } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Like, Repository } from 'typeorm';
import { Media, MediaFileType } from './media.entity';

export interface MediaQuery {
  search?: string;
  fileType?: string;
  page?: number;
  limit?: number;
}

@Injectable()
export class MediaService {
  constructor(
    @InjectRepository(Media)
    private readonly mediaRepo: Repository<Media>,
  ) {}

  /** Coarse category used for filtering the library; derived from the MIME type. */
  static classify(mimeType: string): MediaFileType {
    if (mimeType.startsWith('image/')) return 'IMAGE';
    if (mimeType.startsWith('video/')) return 'VIDEO';
    if (mimeType.startsWith('audio/')) return 'AUDIO';
    if (mimeType === 'application/pdf') return 'DOCUMENT';
    return 'OTHER';
  }

  create(media: Partial<Media>): Promise<Media> {
    return this.mediaRepo.save(this.mediaRepo.create(media));
  }

  async findAll(query: MediaQuery = {}) {
    const page = Math.max(1, Number(query.page) || 1);
    const limit = Math.min(200, Math.max(1, Number(query.limit) || 50));

    const base: Record<string, any> = { status: 'ACTIVE' };
    if (query.fileType) base.fileType = query.fileType;

    const where = query.search
      ? [
          { ...base, fileName: Like(`%${query.search}%`) },
          { ...base, caption: Like(`%${query.search}%`) },
        ]
      : base;

    const [items, total] = await this.mediaRepo.findAndCount({
      where,
      order: { createdAt: 'DESC' },
      skip: (page - 1) * limit,
      take: limit,
    });

    return {
      items,
      meta: { page, limit, total, totalPages: Math.ceil(total / limit) },
    };
  }

  findById(id: number): Promise<Media | null> {
    return this.mediaRepo.findOne({ where: { id } });
  }

  async update(
    id: number,
    data: { caption?: string; altText?: string; fileName?: string },
  ): Promise<Media> {
    const media = await this.findById(id);
    if (!media) throw new NotFoundException('Media not found');
    Object.assign(media, data);
    return this.mediaRepo.save(media);
  }

  /** Soft delete - the file stays on disk so published content does not break. */
  async delete(id: number): Promise<boolean> {
    const result = await this.mediaRepo.update(id, { status: 'DELETED' });
    return (result.affected || 0) > 0;
  }
}
