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

export interface CreateLeadDto {
  name: string; nameNe?: string; phone?: string; email?: string; address?: string;
  source?: string; status?: string; interestedIn?: string; estimatedAmount?: number;
  followUpDate?: string; assignedToId?: string; assignedToName?: string;
  officeId?: string; referredByMemberId?: string; referredByName?: string; remarks?: string;
}
export type UpdateLeadDto = Partial<CreateLeadDto> & { convertedMemberId?: string; convertedDate?: string };

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

  async findAll(sub: string, opts: { status?: string; source?: string; assignedToId?: string; q?: string; page?: number; limit?: number }) {
    const r = await this.repo(sub);
    const { status, source, assignedToId, q, page = 1, limit = 20 } = opts;
    const qb = r.createQueryBuilder('l').where('l.deletedAt IS NULL').orderBy('l.createdAt', 'DESC').skip((page - 1) * limit).take(limit);
    if (status) qb.andWhere('l.status = :status', { status });
    if (source) qb.andWhere('l.source = :source', { source });
    if (assignedToId) qb.andWhere('l.assignedToId = :assignedToId', { assignedToId });
    if (q) qb.andWhere('(l.name LIKE :q OR l.nameNe LIKE :q OR l.phone LIKE :q OR l.email 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, newLeads, contacted, interested, followUp, converted, lost] = await Promise.all([
      r.count({ where: {} }),
      r.count({ where: { status: 'new' } }),
      r.count({ where: { status: 'contacted' } }),
      r.count({ where: { status: 'interested' } }),
      r.count({ where: { status: 'follow_up' } }),
      r.count({ where: { status: 'converted' } }),
      r.count({ where: { status: 'lost' } }),
    ]);
    return { total, new: newLeads, contacted, interested, followUp, converted, lost };
  }

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

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

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

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