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

const RECENT_LIMIT = 50;
const SEARCH_HISTORY_LIMIT = 20;

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

  // ═══ Recent Items ═══

  async findRecentItems(userId: string, limit = 20) {
    return this.prisma.recentItem.findMany({
      where: { userId },
      orderBy: { accessedAt: 'desc' },
      take: limit,
    });
  }

  async upsertRecentItem(userId: string, targetType: string, targetId: string, title: string, metadata?: any) {
    const existing = await this.prisma.recentItem.findFirst({
      where: { userId, targetType, targetId },
    });

    if (existing) {
      await this.prisma.recentItem.update({
        where: { id: existing.id },
        data: { title, metadata, accessedAt: new Date() },
      });
    } else {
      await this.prisma.recentItem.create({
        data: { userId, targetType, targetId, title, metadata },
      });
    }

    const count = await this.prisma.recentItem.count({ where: { userId } });
    if (count > RECENT_LIMIT) {
      const oldest = await this.prisma.recentItem.findMany({
        where: { userId },
        orderBy: { accessedAt: 'asc' },
        take: count - RECENT_LIMIT,
      });
      if (oldest.length > 0) {
        await this.prisma.recentItem.deleteMany({
          where: { id: { in: oldest.map((o) => o.id) } },
        });
      }
    }
  }

  // ═══ Favorites ═══

  async findFavorites(userId: string, limit = 50) {
    return this.prisma.favorite.findMany({
      where: { userId },
      orderBy: { createdAt: 'desc' },
      take: limit,
    });
  }

  async addFavorite(userId: string, targetType: string, targetId: string, title?: string, metadata?: any) {
    return this.prisma.favorite.upsert({
      where: {
        userId_targetType_targetId: { userId, targetType, targetId },
      },
      update: { title, metadata },
      create: { userId, targetType, targetId, title, metadata },
    });
  }

  async removeFavorite(userId: string, id: string) {
    return this.prisma.favorite.deleteMany({ where: { id, userId } });
  }

  async findFavoriteById(id: string) {
    return this.prisma.favorite.findUnique({ where: { id } });
  }

  // ═══ Tags ═══

  async findTags(userId: string) {
    return this.prisma.tag.findMany({ where: { userId }, orderBy: { name: 'asc' } });
  }

  async findTagById(id: string) {
    return this.prisma.tag.findUnique({ where: { id } });
  }

  async createTag(userId: string, name: string, color?: string) {
    return this.prisma.tag.create({ data: { userId, name, color } });
  }

  async updateTag(id: string, data: { name?: string; color?: string }) {
    return this.prisma.tag.update({ where: { id }, data });
  }

  async deleteTag(id: string) {
    return this.prisma.tag.delete({ where: { id } });
  }

  // ═══ KnowledgeItem-Tag ═══

  async findItemTags(knowledgeItemId: string) {
    return this.prisma.knowledgeItemTag.findMany({
      where: { knowledgeItemId },
      include: { tag: true },
    });
  }

  async attachTag(knowledgeItemId: string, tagId: string) {
    return this.prisma.knowledgeItemTag.upsert({
      where: {
        knowledgeItemId_tagId: { knowledgeItemId, tagId },
      },
      update: {},
      create: { knowledgeItemId, tagId },
    });
  }

  async detachTag(knowledgeItemId: string, tagId: string) {
    return this.prisma.knowledgeItemTag.deleteMany({
      where: { knowledgeItemId, tagId },
    });
  }

  // ═══ Search ═══

  async searchKnowledgeBases(userId: string, query: string, limit: number, offset: number) {
    return this.prisma.knowledgeBase.findMany({
      where: {
        userId,
        deletedAt: null,
        title: { contains: query },
      },
      orderBy: { lastStudiedAt: { sort: 'desc', nulls: 'last' } },
      take: limit,
      skip: offset,
    });
  }

  async searchKnowledgeItems(userId: string, query: string, limit: number, offset: number) {
    return this.prisma.knowledgeItem.findMany({
      where: {
        userId,
        deletedAt: null,
        OR: [
          { title: { contains: query } },
          { content: { contains: query } },
        ],
      },
      orderBy: { updatedAt: 'desc' },
      take: limit,
      skip: offset,
    });
  }

  // ═══ Search History ═══

  async addSearchHistory(userId: string, query: string, resultsCount: number) {
    await this.prisma.searchHistory.create({
      data: { userId, query, resultsCount },
    });

    const count = await this.prisma.searchHistory.count({ where: { userId } });
    if (count > SEARCH_HISTORY_LIMIT) {
      const oldest = await this.prisma.searchHistory.findMany({
        where: { userId },
        orderBy: { createdAt: 'asc' },
        take: count - SEARCH_HISTORY_LIMIT,
      });
      if (oldest.length > 0) {
        await this.prisma.searchHistory.deleteMany({
          where: { id: { in: oldest.map((o) => o.id) } },
        });
      }
    }
  }

  async findSearchHistory(userId: string, limit = 20) {
    return this.prisma.searchHistory.findMany({
      where: { userId },
      orderBy: { createdAt: 'desc' },
      take: limit,
    });
  }

  // ═══ Dashboard data ═══

  async countDueReviews(userId: string) {
    return this.prisma.reviewCard.count({
      where: { userId, nextReviewAt: { lte: new Date() }, status: 'active' },
    });
  }

  async findRecentKnowledgeBases(userId: string, limit = 5) {
    return this.prisma.knowledgeBase.findMany({
      where: { userId, deletedAt: null },
      orderBy: { lastStudiedAt: { sort: 'desc', nulls: 'last' } },
      take: limit,
    });
  }

  async countWeeklySessions(userId: string) {
    const weekAgo = new Date(Date.now() - 7 * 86400000);
    const sessions = await this.prisma.learningSession.findMany({
      where: { userId, startedAt: { gte: weekAgo } },
      select: { durationSeconds: true },
    });
    return sessions.reduce((sum, s) => sum + (s.durationSeconds || 0), 0);
  }
}
