/**
 * Inventory Service
 *
 * Replaces: DoMG, UnDoMG from TAmzServerImpl
 * Posts/unposts inventory movements (mgdaily_tr) to items (mg_stor)
 *
 * Original: db_cr=2 (credit) = stock in (ent_qunt), db_cr=1 (debit) = stock out (ext_qunt)
 * Simplified: Update items.mg_stor by +/- qn_ttin
 */
import { Injectable, BadRequestException } from '@nestjs/common';
import { PrismaService } from '../prisma/prisma.service';

@Injectable()
export class InventoryService {
  constructor(private prisma: PrismaService) {}

  private isIn(dbCr: string | null): boolean {
    return dbCr === '2' || dbCr === 'C' || dbCr === 'c';
  }

  /**
   * DoMG(N, kind, ref) - Post inventory movement to items
   */
  async doMG(n: number, kind: number, ref: number): Promise<{ success: boolean }> {
    const rows = await this.prisma.mgdailyTr.findMany({
      where: { kind, ref, tranNo: n, tranSq: { not: 99000 } },
      orderBy: [{ tranSq: 'asc' }],
    });

    if (rows.length === 0) {
      throw new BadRequestException(`No mgdaily entries for kind=${kind}, ref=${ref}, tran_no=${n}`);
    }

    for (const row of rows) {
      const dayMg = row.dayMg;
      const dayMt = row.dayMt;
      if (!dayMg || !dayMt) {
        throw new BadRequestException(`Missing day_mg/day_mt in entry tran_sq=${row.tranSq}`);
      }

      const qty = row.qnTtin ?? 0;
      const isIn = this.isIn(row.dbCr);

      const items = await this.prisma.item.findMany({
        where: { mgNo: dayMg, mtNo: dayMt },
      });

      for (const item of items) {
        const delta = isIn ? qty : -qty;
        await this.prisma.item.update({
          where: {
            mgNo_mtNo_mtrCode: { mgNo: item.mgNo, mtNo: item.mtNo, mtrCode: item.mtrCode },
          },
          data: { mgStor: { increment: delta } },
        });
      }
    }

    return { success: true };
  }

  /**
   * UnDoMG(N, kind, ref) - Unpost inventory movement from items
   */
  async unDoMG(n: number, kind: number, ref: number): Promise<{ success: boolean }> {
    const rows = await this.prisma.mgdailyTr.findMany({
      where: { kind, ref, tranNo: n, tranSq: { not: 99000 } },
      orderBy: [{ tranSq: 'asc' }],
    });

    if (rows.length === 0) {
      throw new BadRequestException(`No mgdaily entries for kind=${kind}, ref=${ref}, tran_no=${n}`);
    }

    for (const row of rows) {
      const dayMg = row.dayMg;
      const dayMt = row.dayMt;
      if (!dayMg || !dayMt) continue;

      const qty = row.qnTtin ?? 0;
      const isIn = this.isIn(row.dbCr);
      const delta = isIn ? -qty : qty;

      const items = await this.prisma.item.findMany({
        where: { mgNo: dayMg, mtNo: dayMt },
      });

      for (const item of items) {
        await this.prisma.item.update({
          where: {
            mgNo_mtNo_mtrCode: { mgNo: item.mgNo, mtNo: item.mtNo, mtrCode: item.mtrCode },
          },
          data: { mgStor: { increment: delta } },
        });
      }
    }

    return { success: true };
  }
}
