import { Injectable, NotFoundException } from '@nestjs/common';
import { TenantConnectionService } from '../../database/tenant-connection.service';
import { Document } from '../../database/tenant/entities/document.entity';

export interface CreateDocumentDto {
  name: string; nameNe?: string; category?: string;
  filePath?: string; fileSize?: number; mimeType?: string; fileExtension?: string;
  description?: string; tags?: string; ocrText?: string;
  memberId?: string; memberName?: string;
  relatedEntityId?: string; relatedEntityType?: string;
  officeId?: string; isPublic?: boolean;
}
export type UpdateDocumentDto = Partial<CreateDocumentDto>;

@Injectable()
export class DocumentsService {
  constructor(private tenantConn: TenantConnectionService) {}
  private async repo(sub: string) {
    const ds = await this.tenantConn.getTenantDataSource(sub);
    return ds.getRepository(Document);
  }

  async findAll(sub: string, opts: { category?: string; memberId?: string; relatedEntityId?: string; q?: string; page?: number; limit?: number }) {
    const r = await this.repo(sub);
    const { category, memberId, relatedEntityId, q, page = 1, limit = 20 } = opts;
    const qb = r.createQueryBuilder('d').where('d.deletedAt IS NULL').orderBy('d.createdAt', 'DESC').skip((page - 1) * limit).take(limit);
    if (category) qb.andWhere('d.category = :category', { category });
    if (memberId) qb.andWhere('d.memberId = :memberId', { memberId });
    if (relatedEntityId) qb.andWhere('d.relatedEntityId = :relatedEntityId', { relatedEntityId });
    if (q) qb.andWhere('(d.name LIKE :q OR d.nameNe LIKE :q OR d.description LIKE :q OR d.tags LIKE :q OR d.memberName LIKE :q)', { q: `%${q}%` });
    const [items, total] = await qb.getManyAndCount();
    const summary = await this.summary(sub);
    return { items, total, page, limit, summary };
  }

  async summary(sub: string) {
    const r = await this.repo(sub);
    const total = await r.count();
    const qb = r.createQueryBuilder('d').select('d.category', 'category').addSelect('COUNT(*)', 'count').where('d.deletedAt IS NULL').groupBy('d.category');
    const byCategory = await qb.getRawMany();
    return { total, byCategory };
  }

  async findOne(sub: string, id: string) {
    const r = await this.repo(sub);
    const d = await r.findOne({ where: { id } });
    if (!d) throw new NotFoundException('Document not found');
    return d;
  }

  async create(sub: string, dto: CreateDocumentDto, userId?: string, userName?: string) {
    const r = await this.repo(sub);
    return r.save(r.create({ ...(dto as any), uploadedById: userId, uploadedByName: userName }));
  }

  async update(sub: string, id: string, dto: UpdateDocumentDto) {
    const r = await this.repo(sub);
    const d = await this.findOne(sub, id);
    Object.assign(d, dto);
    return r.save(d);
  }

  async remove(sub: string, id: string) {
    const r = await this.repo(sub);
    await this.findOne(sub, id);
    await r.softDelete(id);
    return { id };
  }
}
