import { Injectable } from '@nestjs/common';
import { PrismaService } from '../../infrastructure/database/prisma.service';

function detectSourceType(content?: string | null, title?: string): string | null {
  if (!content) return null;

  // COS presigned URL: extract extension from the path
  if (content.includes('.cos.') && content.includes('myqcloud.com')) {
    try {
      const pathname = new URL(content).pathname.toLowerCase();
      const ext = pathname.split('.').pop();
      const extMap: Record<string, string> = {
        pdf: 'pdf', md: 'markdown', markdown: 'markdown',
        txt: 'text', html: 'html', htm: 'html',
        png: 'image', jpg: 'image', jpeg: 'image', webp: 'image', gif: 'image',
        doc: 'word', docx: 'word', xls: 'excel', xlsx: 'excel',
        ppt: 'powerpoint', pptx: 'powerpoint', epub: 'epub',
      };
      if (ext && extMap[ext]) return extMap[ext];
    } catch { /* URL parse fail, fall through */ }
  }

  // HTML content
  if (content.trimStart().startsWith('<')) return 'html';

  // Markdown patterns
  if (/^#{1,6}\s/.test(content) || /^[-*]\s/.test(content) || /\[.+?\]\(.+?\)/.test(content)) {
    return 'markdown';
  }

  // Title-based hint
  if (title) {
    const ext = title.split('.').pop()?.toLowerCase();
    if (ext === 'md') return 'markdown';
    if (ext === 'txt') return 'text';
    if (ext === 'pdf') return 'pdf';
    if (ext === 'html') return 'html';
  }

  return 'text';
}

@Injectable()
export class KnowledgeItemsRepository {
  constructor(private readonly prisma: PrismaService) {}

  async create(userId: string, knowledgeBaseId: string, dto: {
    title?: string;
    content?: string;
    parentId?: string;
    itemType?: string;
    sourceId?: string;
    sourceType?: string;
    sourceRef?: string;
    durationSeconds?: number;
    fileSize?: number;
    orderIndex?: number;
  }) {
    const sourceType = dto.sourceType || detectSourceType(dto.content, dto.title);
    const item = await this.prisma.knowledgeItem.create({
      data: {
        userId,
        knowledgeBaseId,
        title: dto.title ?? '',
        content: dto.content ?? '',
        parentId: dto.parentId ?? null,
        itemType: dto.itemType ?? 'lesson',
        sourceType,
        sourceId: dto.sourceId ?? null,
        sourceRef: dto.sourceRef ?? null,
        durationSeconds: dto.durationSeconds ?? 0,
        fileSize: dto.fileSize ?? null,
        orderIndex: dto.orderIndex ?? 0,
      },
    });

    // 更新知识库 itemCount
    await this.prisma.knowledgeBase.update({
      where: { id: knowledgeBaseId },
      data: { itemCount: { increment: 1 } },
    });

    return item;
  }

  async findById(id: string) {
    return this.prisma.knowledgeItem.findUnique({ where: { id } });
  }

  async findByKnowledgeBaseId(knowledgeBaseId: string, opts?: { sortBy?: string; order?: string }) {
    const validSortBy = ['createdAt', 'updatedAt', 'fileSize', 'default'];
    const sortBy = (opts?.sortBy && validSortBy.includes(opts.sortBy)) ? opts.sortBy : 'default';
    const order = opts?.order === 'asc' ? 'asc' : 'desc';

    let orderBy: any;
    switch (sortBy) {
      case 'createdAt':
        orderBy = { createdAt: order };
        break;
      case 'updatedAt':
        orderBy = { updatedAt: order };
        break;
      case 'fileSize':
        orderBy = { fileSize: order };
        break;
      default:
        orderBy = { orderIndex: 'asc' };
        break;
    }

    return this.prisma.knowledgeItem.findMany({
      where: { knowledgeBaseId, deletedAt: null },
      orderBy,
    });
  }

  async update(id: string, dto: Record<string, any>) {
    // Whitelist allowed fields to prevent mass assignment
    const allowed = ['title', 'content', 'summary', 'parentId', 'itemType', 'sourceType', 'sourceRef', 'orderIndex', 'status', 'durationSeconds'];
    const data: Record<string, any> = {};
    for (const key of allowed) {
      if (dto[key] !== undefined) data[key] = dto[key];
    }
    return this.prisma.knowledgeItem.update({
      where: { id },
      data,
    });
  }

  async softDelete(id: string) {
    const item = await this.prisma.knowledgeItem.update({
      where: { id },
      data: { deletedAt: new Date() },
    });

    // 更新知识库 itemCount
    await this.prisma.knowledgeBase.update({
      where: { id: item.knowledgeBaseId },
      data: { itemCount: { decrement: 1 } },
    });

    return item;
  }
}
