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

export interface CreateDepositAccountDto {
  memberId: string;
  memberName: string;
  memberCode?: string;
  savingType?: string;
  savingTypeName?: string;
  duration?: string;
  durationType?: string;
  principalAmount?: number;
  interestPercent?: number;
  interestReceiveType?: string;
  openDate?: string;
  openDateBs?: string;
  maturityDate?: string;
  maturityDateBs?: string;
  isJointAccount?: boolean;
  jointMemberName?: string;
  officeId?: string;
  remarks?: string;
}

export type UpdateDepositAccountDto = Partial<CreateDepositAccountDto> & {
  status?: string;
  totalInterestEarned?: number;
  totalWithdrawn?: number;
};

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

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

  async findAll(sub: string, opts: { status?: string; savingType?: string; q?: string; page?: number; limit?: number }) {
    const r = await this.repo(sub);
    const { status, savingType, 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 (status) qb.andWhere('d.status = :status', { status });
    if (savingType) qb.andWhere('d.savingType = :savingType', { savingType });
    if (q) qb.andWhere('(d.memberName LIKE :q OR d.accountNumber LIKE :q OR d.memberCode 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 d = await r.findOne({ where: { id } });
    if (!d) throw new NotFoundException('Deposit account not found');
    return d;
  }

  async create(sub: string, dto: CreateDepositAccountDto, userId?: string, userName?: string) {
    const r = await this.repo(sub);
    const accountNumber = await this.nextAccountNumber(sub);
    return r.save(r.create({
      ...(dto as any),
      accountNumber,
      status: 'pending',
      totalInterestEarned: 0,
      totalWithdrawn: 0,
      createdById: userId,
      createdByName: userName,
    }));
  }

  async update(sub: string, id: string, dto: UpdateDepositAccountDto) {
    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);
    const d = await this.findOne(sub, id);
    d.deletedAt = new Date();
    await r.save(d);
    return { ok: true };
  }

  async summary(sub: string) {
    const r = await this.repo(sub);
    const [total, pending, active, matured, closed] = await Promise.all([
      r.count({ where: {} }),
      r.count({ where: { status: 'pending' } }),
      r.count({ where: { status: 'active' } }),
      r.count({ where: { status: 'matured' } }),
      r.count({ where: { status: 'closed' } }),
    ]);
    return { total, pending, active, matured, closed };
  }
}
