import { Injectable, NotFoundException } from '@nestjs/common';
import { PrismaService } from '@chatapp/database';

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

  async listByChannel(channelId: string, wsId: string) {
    const canvases = await this.prisma.canvas.findMany({
      where: { channelId, workspaceId: wsId },
      orderBy: { updatedAt: 'desc' },
      include: {
        createdByUser: { select: { id: true, displayName: true, avatarUrl: true } },
        lastEditedByUser: { select: { id: true, displayName: true } },
        _count: { select: { collaborators: true } },
      },
    });

    return {
      canvases: canvases.map(c => ({
        id: c.id,
        title: c.title,
        channel_id: c.channelId,
        version: c.version,
        is_template: c.isTemplate,
        created_by: c.createdByUser,
        last_edited_by: c.lastEditedByUser,
        collaborator_count: c._count.collaborators,
        created_at: c.createdAt,
        updated_at: c.updatedAt,
      })),
    };
  }

  async create(channelId: string, wsId: string, userId: string, dto: any) {
    const canvas = await this.prisma.canvas.create({
      data: {
        workspaceId: wsId,
        channelId,
        title: dto.title,
        content: dto.content || {},
        documentId: crypto.randomUUID(),
        isTemplate: dto.is_template ?? false,
        templateCategory: dto.template_category,
        createdBy: userId,
        lastEditedBy: userId,
      },
      include: {
        createdByUser: { select: { id: true, displayName: true, avatarUrl: true } },
      },
    });

    // Add creator as collaborator with edit permission
    await this.prisma.canvasCollaborator.create({
      data: {
        canvasId: canvas.id,
        userId,
        permission: 'edit',
      },
    });

    return canvas;
  }

  async findById(id: string, wsId: string) {
    const canvas = await this.prisma.canvas.findFirst({
      where: { id, workspaceId: wsId },
      include: {
        createdByUser: { select: { id: true, displayName: true, avatarUrl: true } },
        lastEditedByUser: { select: { id: true, displayName: true } },
        collaborators: {
          include: {
            user: { select: { id: true, displayName: true, avatarUrl: true } },
          },
        },
      },
    });

    if (!canvas) throw new NotFoundException('Canvas not found');

    return {
      id: canvas.id,
      title: canvas.title,
      content: canvas.content,
      document_id: canvas.documentId,
      version: canvas.version,
      is_template: canvas.isTemplate,
      template_category: canvas.templateCategory,
      created_by: canvas.createdByUser,
      last_edited_by: canvas.lastEditedByUser,
      collaborators: canvas.collaborators.map(c => ({
        user: c.user,
        permission: c.permission,
        added_at: c.addedAt,
      })),
      created_at: canvas.createdAt,
      updated_at: canvas.updatedAt,
    };
  }

  async update(id: string, wsId: string, userId: string, dto: any) {
    const canvas = await this.prisma.canvas.findFirst({
      where: { id, workspaceId: wsId },
    });
    if (!canvas) throw new NotFoundException('Canvas not found');

    const data: any = {
      lastEditedBy: userId,
      version: { increment: 1 },
    };
    if (dto.title !== undefined) data.title = dto.title;
    if (dto.content !== undefined) data.content = dto.content;
    if (dto.blocks !== undefined) {
      // Merge blocks into content
      data.content = { ...(canvas.content as any), blocks: dto.blocks };
    }
    if (dto.text !== undefined) {
      data.content = { ...(canvas.content as any), text: dto.text };
    }

    return this.prisma.canvas.update({
      where: { id },
      data,
      include: {
        lastEditedByUser: { select: { id: true, displayName: true } },
      },
    });
  }

  async addCollaborator(id: string, wsId: string, dto: any) {
    const canvas = await this.prisma.canvas.findFirst({
      where: { id, workspaceId: wsId },
    });
    if (!canvas) throw new NotFoundException('Canvas not found');

    const collaborator = await this.prisma.canvasCollaborator.upsert({
      where: {
        canvasId_userId: {
          canvasId: id,
          userId: dto.user_id,
        },
      },
      create: {
        canvasId: id,
        userId: dto.user_id,
        permission: dto.permission || 'edit',
      },
      update: {
        permission: dto.permission || 'edit',
      },
      include: {
        user: { select: { id: true, displayName: true, avatarUrl: true } },
      },
    });

    return collaborator;
  }
}