import { Injectable, NotFoundException } from '@nestjs/common';
import { TenantConnectionService } from '../../database/tenant-connection.service';
import { requireCurrentTenant } from '../../database/tenant-context';
import { Share } from '../../database/tenant/entities/share.entity';

export interface CreateShareDto {
  memberId?: string;
  memberCode?: string;
  memberName?: string;
  shareType?: string;
  numberOfShares?: string;
  faceValue?: string;
  purchaseAmount?: string;
  purchaseDate?: string;
  purchaseDateBs?: string;
  fiscalYear?: string;
  certificateIssuedDate?: string;
  certificateIssuedDateBs?: string;
  officeId?: string;
  remarks?: string;
}

export interface TransferShareDto {
  transferredToMemberId: string;
  transferredToMemberName: string;
  transferDate?: string;
  transferDateBs?: string;
  remarks?: string;
}

export type UpdateShareDto = Partial<CreateShareDto> & {
  status?: string;
  certificateNumber?: string;
};

@Injectable()
export class SharesService {
  constructor(private tenantConn: TenantConnectionService) {}

  private sub() { return requireCurrentTenant().subdomain; }
  private async repo() {
    const ds = await this.tenantConn.getTenantDataSource(this.sub());
    return ds.getRepository(Share);
  }

  private async nextShareNumber(): Promise<string> {
    const r = await this.repo();
    const count = await r.count();
    return `SHR-${String(count + 1).padStart(6, '0')}`;
  }

  async findAll(opts: { q?: string; shareType?: string; status?: string; memberId?: string; page?: number; limit?: number }) {
    const r = await this.repo();
    const { q, shareType, status, memberId, page = 1, limit = 20 } = opts;
    const qb = r.createQueryBuilder('s').orderBy('s.createdAt', 'DESC').skip((page - 1) * limit).take(limit);
    if (shareType) qb.andWhere('s.shareType = :shareType', { shareType });
    if (status) qb.andWhere('s.status = :status', { status });
    if (memberId) qb.andWhere('s.memberId = :memberId', { memberId });
    if (q) qb.andWhere('(s.memberName LIKE :q OR s.shareNumber LIKE :q OR s.memberCode LIKE :q OR s.certificateNumber LIKE :q)', { q: `%${q}%` });
    const [items, total] = await qb.getManyAndCount();
    return { items, total, page, limit };
  }

  async findOne(id: string) {
    const r = await this.repo();
    const s = await r.findOne({ where: { id } });
    if (!s) throw new NotFoundException('Share record not found');
    return s;
  }

  async create(dto: CreateShareDto) {
    const r = await this.repo();
    const shareNumber = await this.nextShareNumber();
    const certNum = `CERT-${shareNumber.replace('SHR-', '')}`;
    return r.save(r.create({ ...dto, shareNumber, certificateNumber: certNum, status: 'active' } as any));
  }

  async update(id: string, dto: UpdateShareDto) {
    const r = await this.repo();
    const s = await this.findOne(id);
    return r.save({ ...s, ...dto });
  }

  async transfer(id: string, dto: TransferShareDto) {
    const r = await this.repo();
    const s = await this.findOne(id);
    return r.save({ ...s, ...dto, status: 'transferred' });
  }

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

  async getSummary(memberId?: string) {
    const r = await this.repo();
    const qb = r.createQueryBuilder('s');
    if (memberId) qb.where('s.memberId = :memberId', { memberId });
    const all = await qb.getMany();
    const active = all.filter(s => s.status === 'active');
    const totalShares = active.reduce((sum, s) => sum + Number(s.numberOfShares ?? 0), 0);
    const totalAmount = active.reduce((sum, s) => sum + Number(s.purchaseAmount ?? 0), 0);
    const byType: Record<string, { count: number; shares: number; amount: number }> = {};
    for (const s of active) {
      const t = s.shareType ?? 'general';
      if (!byType[t]) byType[t] = { count: 0, shares: 0, amount: 0 };
      byType[t].count++;
      byType[t].shares += Number(s.numberOfShares ?? 0);
      byType[t].amount += Number(s.purchaseAmount ?? 0);
    }
    return { totalRecords: all.length, activeRecords: active.length, totalShares, totalAmount, byType };
  }
}
