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

export interface CreateMinuteDto {
  meetingType: string; meetingDate: string; meetingDateBs?: string; meetingTime?: string;
  fiscalYear?: string; venue?: string; chairperson?: string; secretary?: string;
  totalAttendees?: number; attendees?: string; agenda?: string; decisions?: string;
  nextMeetingDate?: string; status?: string; approvedBy?: string; approvedDate?: string;
  officeId?: string; remarks?: string;
}
export type UpdateMinuteDto = Partial<CreateMinuteDto>;

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

  private async nextNumber(sub: string, meetingType: string, fiscalYear?: string): Promise<string> {
    const r = await this.repo(sub);
    const qb = r.createQueryBuilder('m').where('m.meetingType = :meetingType', { meetingType });
    if (fiscalYear) qb.andWhere('m.fiscalYear = :fiscalYear', { fiscalYear });
    const count = await qb.getCount();
    const prefix = meetingType.toUpperCase().slice(0, 3);
    const fy = (fiscalYear ?? new Date().getFullYear().toString()).slice(-4);
    return `${prefix}-${fy}-${String(count + 1).padStart(3, '0')}`;
  }

  async findAll(sub: string, opts: { meetingType?: string; status?: string; fiscalYear?: string; q?: string; page?: number; limit?: number }) {
    const r = await this.repo(sub);
    const { meetingType, status, fiscalYear, q, page = 1, limit = 20 } = opts;
    const qb = r.createQueryBuilder('m').where('m.deletedAt IS NULL').orderBy('m.meetingDate', 'DESC').skip((page - 1) * limit).take(limit);
    if (meetingType) qb.andWhere('m.meetingType = :meetingType', { meetingType });
    if (status) qb.andWhere('m.status = :status', { status });
    if (fiscalYear) qb.andWhere('m.fiscalYear = :fiscalYear', { fiscalYear });
    if (q) qb.andWhere('(m.minuteNumber LIKE :q OR m.chairperson LIKE :q OR m.venue LIKE :q)', { q: `%${q}%` });
    const [items, total] = await qb.getManyAndCount();
    return { items, total, page, limit };
  }

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

  async create(sub: string, dto: CreateMinuteDto, userId?: string, userName?: string) {
    const r = await this.repo(sub);
    const minuteNumber = await this.nextNumber(sub, dto.meetingType, dto.fiscalYear);
    return r.save(r.create({ ...(dto as any), minuteNumber, status: dto.status ?? 'draft', createdById: userId, createdByName: userName }));
  }

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

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