import { ForbiddenException, Injectable, NotFoundException } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { Annotation } from './annotation.entity';
import { SaveAnnotationDto, UpdateAnnotationDto } from './dto/annotation.dto';

@Injectable()
export class AnnotationsService {
  constructor(
    @InjectRepository(Annotation)
    private readonly repo: Repository<Annotation>,
  ) {}

  async save(dto: SaveAnnotationDto): Promise<Annotation> {
    if (dto.activityId) {
      const existing = await this.repo.findOne({
        where: {
          anonymousSessionId: dto.anonymousSessionId,
          activityId: dto.activityId,
        },
      });
      if (existing) {
        Object.assign(existing, dto);
        return this.repo.save(existing);
      }
    }
    return this.repo.save(this.repo.create(dto));
  }

  async update(id: number, dto: UpdateAnnotationDto): Promise<Annotation> {
    const annotation = await this.repo.findOne({ where: { id } });
    if (!annotation) throw new NotFoundException('Annotation not found');
    if (annotation.anonymousSessionId !== dto.anonymousSessionId) {
      throw new ForbiddenException('This annotation belongs to a different session');
    }
    Object.assign(annotation, dto);
    return this.repo.save(annotation);
  }

  findBySession(sessionId: string): Promise<Annotation[]> {
    return this.repo.find({
      where: { anonymousSessionId: sessionId },
      order: { updatedAt: 'DESC' },
    });
  }

  findForActivity(sessionId: string, activityId: number): Promise<Annotation | null> {
    return this.repo.findOne({
      where: { anonymousSessionId: sessionId, activityId },
    });
  }

  async delete(id: number, sessionId: string): Promise<boolean> {
    const annotation = await this.repo.findOne({ where: { id } });
    if (!annotation) return false;
    if (annotation.anonymousSessionId !== sessionId) {
      throw new ForbiddenException('This annotation belongs to a different session');
    }
    const result = await this.repo.delete(id);
    return (result.affected || 0) > 0;
  }
}
