import { ConflictException, Injectable, NotFoundException } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { QuickReferenceItem } from './quick-reference-item.entity';
import {
  CreateQuickReferenceDto,
  UpdateQuickReferenceDto,
} from './dto/quick-reference.dto';

export interface QuickReferenceCategory {
  category: string;
  items: QuickReferenceItem[];
}

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

  async create(dto: CreateQuickReferenceDto): Promise<QuickReferenceItem> {
    const existing = await this.repo.findOne({ where: { slug: dto.slug } });
    if (existing) throw new ConflictException('A quick reference item with that slug exists');
    return this.repo.save(this.repo.create(dto));
  }

  findAll(category?: string): Promise<QuickReferenceItem[]> {
    return this.repo.find({
      where: category ? { category } : {},
      order: { category: 'ASC', orderIndex: 'ASC' },
    });
  }

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

  findPublishedBySlug(slug: string): Promise<QuickReferenceItem | null> {
    return this.repo.findOne({ where: { slug, status: 'PUBLISHED' } });
  }

  /** Grouped shape the mobile Quick Reference screen renders directly. */
  async findPublishedGrouped(): Promise<QuickReferenceCategory[]> {
    const items = await this.repo.find({
      where: { status: 'PUBLISHED' },
      order: { category: 'ASC', orderIndex: 'ASC' },
    });

    const groups = new Map<string, QuickReferenceItem[]>();
    for (const item of items) {
      const bucket = groups.get(item.category);
      if (bucket) bucket.push(item);
      else groups.set(item.category, [item]);
    }

    return Array.from(groups.entries()).map(([category, groupItems]) => ({
      category,
      items: groupItems,
    }));
  }

  async update(id: number, dto: UpdateQuickReferenceDto): Promise<QuickReferenceItem> {
    const item = await this.findById(id);
    if (!item) throw new NotFoundException('Quick reference item not found');

    if (dto.slug && dto.slug !== item.slug) {
      const clash = await this.repo.findOne({ where: { slug: dto.slug } });
      if (clash) throw new ConflictException('A quick reference item with that slug exists');
    }

    Object.assign(item, dto);
    return this.repo.save(item);
  }

  async setStatus(id: number, status: string): Promise<QuickReferenceItem> {
    const item = await this.findById(id);
    if (!item) throw new NotFoundException('Quick reference item not found');
    item.status = status;
    return this.repo.save(item);
  }

  async delete(id: number): Promise<boolean> {
    const result = await this.repo.delete(id);
    return (result.affected || 0) > 0;
  }
}
