/**
 * Invoices Controller
 *
 * REST endpoints for fat_sale, fat_buy, etc.
 * Replaces: LastInvoice, HoldSInvoice, DoInvoice, UnDoInvoice, etc.
 */
import { Body, Controller, Get, Post, Query, UseGuards } from '@nestjs/common';
import { InvoicesService } from './invoices.service';
import { JwtAuthGuard } from '../auth/jwt-auth.guard';

@Controller('invoices')
@UseGuards(JwtAuthGuard)
export class InvoicesController {
  constructor(private invoicesService: InvoicesService) {}

  /**
   * GET /api/invoices/sale/last?dft=1&st=0&ref=0
   * Maps to: LastInvoice(dft, st, ref)
   */
  @Get('sale/last')
  async lastSale(
    @Query('dft') dft: string,
    @Query('st') st: string,
    @Query('ref') ref: string,
  ) {
    const n = await this.invoicesService.getLastSaleInvoice(
      parseInt(dft || '1', 10),
      parseInt(st || '0', 10),
      parseInt(ref || '0', 10),
    );
    return { lastInvoice: n };
  }

  /**
   * GET /api/invoices/sale/hold?dft=1&ref=0
   * Maps to: HoldSInvoice(dft, st, ref)
   */
  @Get('sale/hold')
  async holdSale(
    @Query('dft') dft: string,
    @Query('ref') ref: string,
  ) {
    const count = await this.invoicesService.holdSaleInvoice(
      parseInt(dft || '1', 10),
      parseInt(ref || '0', 10),
    );
    return { holdSInvoice: count };
  }

  /**
   * GET /api/invoices/buy/last?dft=1&st=0&ref=0
   * Maps to: LastBuyInvoice(dft, st, ref)
   */
  @Get('buy/last')
  async lastBuy(
    @Query('dft') dft: string,
    @Query('st') st: string,
    @Query('ref') ref: string,
  ) {
    const n = await this.invoicesService.getLastBuyInvoice(
      parseInt(dft || '1', 10),
      parseInt(st || '0', 10),
      parseInt(ref || '0', 10),
    );
    return { lastBuyInvoice: n };
  }

  /**
   * GET /api/invoices/buy/hold?dft=1&ref=0
   */
  @Get('buy/hold')
  async holdBuy(
    @Query('dft') dft: string,
    @Query('ref') ref: string,
  ) {
    const count = await this.invoicesService.holdBuyInvoice(
      parseInt(dft || '1', 10),
      parseInt(ref || '0', 10),
    );
    return { holdBuyInvoice: count };
  }

  /** LastBBack, HoldBBackInvoice */
  @Get('bback/last')
  async lastBBack(
    @Query('dft') dft: string,
    @Query('st') st: string,
    @Query('ref') ref: string,
  ) {
    const n = await this.invoicesService.getLastBBack(
      parseInt(dft || '1', 10),
      parseInt(st || '0', 10),
      parseInt(ref || '0', 10),
    );
    return { lastBBack: n };
  }

  @Get('bback/hold')
  async holdBBack(@Query('dft') dft: string, @Query('ref') ref: string) {
    const count = await this.invoicesService.holdBBackInvoice(
      parseInt(dft || '1', 10),
      parseInt(ref || '0', 10),
    );
    return { holdBBackInvoice: count };
  }

  /** LastSBack, HoldSBackInvoice */
  @Get('sback/last')
  async lastSBack(
    @Query('dft') dft: string,
    @Query('st') st: string,
    @Query('ref') ref: string,
  ) {
    const n = await this.invoicesService.getLastSBack(
      parseInt(dft || '1', 10),
      parseInt(st || '0', 10),
      parseInt(ref || '0', 10),
    );
    return { lastSBack: n };
  }

  @Get('sback/hold')
  async holdSBack(@Query('dft') dft: string, @Query('ref') ref: string) {
    const count = await this.invoicesService.holdSBackInvoice(
      parseInt(dft || '1', 10),
      parseInt(ref || '0', 10),
    );
    return { holdSBackInvoice: count };
  }

  /** LastPosl, HoldPosl */
  @Get('posl/last')
  async lastPosl(
    @Query('dft') dft: string,
    @Query('st') st: string,
    @Query('ref') ref: string,
  ) {
    const n = await this.invoicesService.getLastPosl(
      parseInt(dft || '1', 10),
      parseInt(st || '0', 10),
      parseInt(ref || '0', 10),
    );
    return { lastPosl: n };
  }

  @Get('posl/hold')
  async holdPosl(@Query('dft') dft: string, @Query('ref') ref: string) {
    const count = await this.invoicesService.holdPosl(
      parseInt(dft || '1', 10),
      parseInt(ref || '0', 10),
    );
    return { holdPosl: count };
  }

  /** LastExInvoice, HoldExInvoice */
  @Get('ex/last')
  async lastEx(
    @Query('dft') dft: string,
    @Query('st') st: string,
    @Query('ref') ref: string,
  ) {
    const n = await this.invoicesService.getLastExInvoice(
      parseInt(dft || '1', 10),
      parseInt(st || '0', 10),
      parseInt(ref || '0', 10),
    );
    return { lastExInvoice: n };
  }

  @Get('ex/hold')
  async holdEx(@Query('dft') dft: string, @Query('ref') ref: string) {
    const count = await this.invoicesService.holdExInvoice(
      parseInt(dft || '1', 10),
      parseInt(ref || '0', 10),
    );
    return { holdExInvoice: count };
  }

  /**
   * POST /api/invoices/sale/do
   * Maps to: DoInvoice(dft, N, ref)
   */
  @Post('sale/do')
  async doSaleInvoice(@Body() body: { dft: number; n: number; ref: number }) {
    const { dft = 1, n, ref = 0 } = body;
    if (n == null) return { success: false, error: 'n is required' };
    return this.invoicesService.doSaleInvoice(dft, n, ref);
  }

  /**
   * POST /api/invoices/sale/undo
   * Maps to: UnDoInvoice(dft, N, ref)
   */
  @Post('sale/undo')
  async unDoSaleInvoice(@Body() body: { dft: number; n: number; ref: number }) {
    const { dft = 1, n, ref = 0 } = body;
    if (n == null) return { success: false, error: 'n is required' };
    return this.invoicesService.unDoSaleInvoice(dft, n, ref);
  }

  /**
   * POST /api/invoices/buy/do
   * Maps to: DoBuyInvoice(dft, N, ref)
   */
  @Post('buy/do')
  async doBuyInvoice(@Body() body: { dft: number; n: number; ref: number }) {
    const { dft = 1, n, ref = 0 } = body;
    if (n == null) return { success: false, error: 'n is required' };
    return this.invoicesService.doBuyInvoice(dft, n, ref);
  }

  /**
   * POST /api/invoices/buy/undo
   * Maps to: UnDoBuyInvoice(dft, N, ref)
   */
  @Post('buy/undo')
  async unDoBuyInvoice(@Body() body: { dft: number; n: number; ref: number }) {
    const { dft = 1, n, ref = 0 } = body;
    if (n == null) return { success: false, error: 'n is required' };
    return this.invoicesService.unDoBuyInvoice(dft, n, ref);
  }

  /**
   * GET /api/invoices/sale/lines?dft=1&n=1&ref=0
   * Get sale invoice lines (SSinvc)
   */
  @Get('sale/lines')
  async getSaleLines(
    @Query('dft') dft: string,
    @Query('n') n: string,
    @Query('ref') ref: string,
  ) {
    return this.invoicesService.getSaleInvoiceLines(
      parseInt(dft || '1', 10),
      parseInt(n || '1', 10),
      parseInt(ref || '0', 10),
    );
  }

  /**
   * GET /api/invoices/sale/list?dft=1&ref=0&sfatTyp=1
   * List sale invoices with optional status filter (SSinvc)
   */
  @Get('sale/list')
  async listSaleInvoices(
    @Query('dft') dft: string,
    @Query('ref') ref: string,
    @Query('sfatTyp') sfatTyp: string,
  ) {
    const typ = sfatTyp ? parseInt(sfatTyp, 10) : undefined;
    return this.invoicesService.listSaleInvoices(
      parseInt(dft || '1', 10),
      parseInt(ref || '0', 10),
      typ,
    );
  }

  /**
   * PUT /api/invoices/sale
   * Create or update sale invoice (SSinvc)
   */
  @Post('sale/save')
  async saveSaleInvoice(
    @Body()
    body: {
      dft: number;
      n: number;
      ref: number;
      sfatTyp?: number;
      sfatBrnch?: number;
      sfatMndb?: number;
      sfatKlfn?: number;
      sfatSalr?: number;
      sfatExprt?: number;
      sfatMncd?: number;
      sfatSlwy?: number;
      sfatPaym?: number;
      lines: Array<{
        sfatSq: number;
        dailyActNo?: string;
        dayMg?: string;
        dayMt?: string;
        sfatMtnm?: string;
        qnTtin?: number;
        sfatPric?: number;
        monVl?: number;
      }>;
    },
  ) {
    const {
      dft = 1,
      n,
      ref = 0,
      sfatTyp,
      sfatBrnch,
      sfatMndb,
      sfatKlfn,
      sfatSalr,
      sfatExprt,
      sfatMncd,
      sfatSlwy,
      sfatPaym,
      lines = [],
    } = body;
    if (n == null) return { success: false, error: 'n is required' };
    const header =
      sfatTyp != null ||
      sfatBrnch != null ||
      sfatMndb != null ||
      sfatKlfn != null ||
      sfatSalr != null ||
      sfatExprt != null ||
      sfatMncd != null ||
      sfatSlwy != null ||
      sfatPaym != null
        ? {
            sfatTyp,
            sfatBrnch,
            sfatMndb,
            sfatKlfn,
            sfatSalr,
            sfatExprt,
            sfatMncd,
            sfatSlwy,
            sfatPaym,
          }
        : undefined;
    const result = await this.invoicesService.createOrUpdateSaleInvoice(
      dft,
      n,
      ref,
      lines.map((l) => ({
        ref,
        dftrNo: dft,
        sfatNo: n,
        sfatSq: l.sfatSq,
        dailyActNo: l.dailyActNo,
        dayMg: l.dayMg,
        dayMt: l.dayMt,
        sfatMtnm: l.sfatMtnm,
        qnTtin: l.qnTtin,
        sfatPric: l.sfatPric,
        monVl: l.monVl,
      })),
      header,
    );
    return { lines: result };
  }

  /**
   * DELETE /api/invoices/sale?dft=1&n=1&ref=0
   * Delete sale invoice
   */
  @Post('sale/delete')
  async deleteSaleInvoice(
    @Body() body: { dft: number; n: number; ref: number },
  ) {
    const { dft = 1, n, ref = 0 } = body;
    if (n == null) return { success: false, error: 'n is required' };
    return this.invoicesService.deleteSaleInvoice(dft, n, ref);
  }
}
