import {
  Body,
  Controller,
  Get,
  Param,
  ParseUUIDPipe,
  Post,
  Query,
  UseGuards,
} from '@nestjs/common';
import { JwtAuthGuard } from '../../auth/guards/jwt-auth.guard';
import { PermissionGuard } from '../../auth/guards/permission.guard';
import { Permissions } from '../../auth/decorators/permissions.decorator';
import { AccessLevel, ModuleName } from '../../entities/role-permission.entity';
import { successResponse } from '../../common/responses/api-response';
import { AccountingService } from './accounting.service';
import { TaxLedgerQueryDto } from './dto/tax-ledger-query.dto';
import { AgingQueryDto } from './dto/aging-query.dto';
import { PnlQueryDto } from './dto/pnl-query.dto';
import { GenerateInvoiceDto } from './dto/generate-invoice.dto';

@Controller('accounting')
@UseGuards(JwtAuthGuard, PermissionGuard)
export class AccountingController {
  constructor(private readonly service: AccountingService) {}

  /**
   * GET /accounting/tax-ledger
   *
   * Aggregated tax ledger across the four booking-item tables filtered
   * by start_date (travel date — FTA supply-date semantic). Cancelled
   * pax emit as negative rows under the same group key so the running
   * totals self-balance when include_cancelled is on (default true).
   */
  @Get('tax-ledger')
  @Permissions({ module: ModuleName.ACCOUNTING, accessLevel: AccessLevel.VIEW })
  async taxLedger(@Query() query: TaxLedgerQueryDto) {
    const result = await this.service.getTaxLedger(query);
    return successResponse(result, 'Tax ledger fetched successfully');
  }

  // Tier-1 Accounting reports — all read-only.

  @Get('receivables-aging')
  @Permissions({ module: ModuleName.ACCOUNTING, accessLevel: AccessLevel.VIEW })
  async receivablesAging(@Query() q: AgingQueryDto) {
    const result = await this.service.getReceivablesAging({ as_of: q.as_of, party: q.party });
    return successResponse(result, 'Receivables aging fetched');
  }

  @Get('payables-aging')
  @Permissions({ module: ModuleName.ACCOUNTING, accessLevel: AccessLevel.VIEW })
  async payablesAging(@Query() q: AgingQueryDto) {
    const result = await this.service.getPayablesAging({ as_of: q.as_of });
    return successResponse(result, 'Payables aging fetched');
  }

  @Get('p-and-l')
  @Permissions({ module: ModuleName.ACCOUNTING, accessLevel: AccessLevel.VIEW })
  async profitAndLoss(@Query() q: PnlQueryDto) {
    const result = await this.service.getProfitAndLoss({
      from: q.from,
      to: q.to,
      group_by: q.group_by ?? null,
    });
    return successResponse(result, 'P&L fetched');
  }

  // Customer Tax Invoice — Tier 1 #105. EDIT permission required to
  // generate; VIEW is enough to read.

  @Post('invoices/generate')
  @Permissions({ module: ModuleName.ACCOUNTING, accessLevel: AccessLevel.EDIT })
  async generateInvoice(@Body() dto: GenerateInvoiceDto) {
    const inv = await this.service.generateCustomerInvoice({
      booking_id: dto.booking_id,
    });
    return successResponse(inv, `Invoice ${inv.invoice_no} generated`);
  }

  @Get('invoices/by-booking/:bookingId')
  @Permissions({ module: ModuleName.ACCOUNTING, accessLevel: AccessLevel.VIEW })
  async listForBooking(@Param('bookingId', ParseUUIDPipe) bookingId: string) {
    const rows = await this.service.findInvoicesForBooking(bookingId);
    return successResponse(rows, 'Invoices for booking');
  }

  @Get('invoices/:id')
  @Permissions({ module: ModuleName.ACCOUNTING, accessLevel: AccessLevel.VIEW })
  async getInvoice(@Param('id', ParseUUIDPipe) id: string) {
    const inv = await this.service.findInvoiceById(id);
    return successResponse(inv, 'Invoice fetched');
  }
}
