import {
  BadRequestException,
  Body,
  Controller,
  Delete,
  Param,
  Patch,
  Post,
  Put,
  Res,
  UseGuards,
} from '@nestjs/common';
import { Response } from 'express';
import { TransactionDataOrchestrator } from '../domain/usecases/transaction-data.orchestrator';
import { TransactionDto } from './dto/transaction.dto';
import { MODULE_NAME } from 'src/core/strings/constants/module.constants';
import { ApiBearerAuth, ApiBody, ApiTags } from '@nestjs/swagger';
import { TransactionEntity } from '../domain/entities/transaction.entity';
import { BatchResult } from 'src/core/response/domain/ok-response.interface';
import { BatchIdsDto } from 'src/core/modules/infrastructure/dto/base-batch.dto';
import { Public } from 'src/core/guards';
import { DownloadPdfDto } from './dto/donwload-pdf.dto';
import { OtpAuthGuard } from 'src/modules/configuration/otp-verification/infrastructure/guards/otp-auth.guard';
import { OtpCheckerGuard } from 'src/core/guards/domain/otp-checker.guard';

@ApiTags(`${MODULE_NAME.TRANSACTION.split('-').join(' ')} - data`)
@Controller(`v1/${MODULE_NAME.TRANSACTION}`)
@Public(false)
@ApiBearerAuth('JWT')
export class TransactionDataController {
  constructor(private orchestrator: TransactionDataOrchestrator) {}

  @Post()
  async create(@Body() data: TransactionDto): Promise<TransactionEntity> {
    return await this.orchestrator.create(data);
  }

  @Put('/:id/invoice/download')
  async invoiceDownload(
    @Param('id') dataId: string,
    @Body() body: DownloadPdfDto,
    @Res() res: Response,
  ): Promise<any> {
    const data = await this.orchestrator.invoice(dataId, body.invoice_type);
    res.setHeader('Content-Type', 'application/pdf');
    res.setHeader('Content-Disposition', 'attachment; filename=invoice.pdf');
    res.send(data);
    return res;
  }

  @Put('/batch-delete')
  async batchDeleted(@Body() body: BatchIdsDto): Promise<BatchResult> {
    return await this.orchestrator.batchDelete(body.ids);
  }

  @Patch(':id/confirm-data')
  @UseGuards(OtpCheckerGuard)
  async confirmData(@Param('id') dataId: string): Promise<string> {
    return await this.orchestrator.confirmData(dataId);
  }

  @Put('/batch-confirm-data')
  async batchConfirmData(@Body() body: BatchIdsDto): Promise<BatchResult> {
    return await this.orchestrator.batchConfirmData(body.ids);
  }

  @Patch(':id/confirm')
  @UseGuards(OtpCheckerGuard)
  async confirm(@Param('id') dataId: string): Promise<string> {
    return await this.orchestrator.confirm(dataId);
  }

  @Put('/batch-confirm')
  async batchConfirm(@Body() body: BatchIdsDto): Promise<BatchResult> {
    return await this.orchestrator.batchConfirm(body.ids);
  }

  @Patch(':id/cancel')
  async cancel(@Param('id') dataId: string): Promise<string> {
    return await this.orchestrator.cancel(dataId);
  }

  @Put('/batch-cancel')
  async batchCancel(@Body() body: BatchIdsDto): Promise<BatchResult> {
    return await this.orchestrator.batchCancel(body.ids);
  }

  @Put(':id')
  async update(
    @Param('id') dataId: string,
    @Body() data: TransactionDto,
  ): Promise<TransactionEntity> {
    return await this.orchestrator.update(dataId, data);
  }

  @Delete(':id')
  async delete(@Param('id') dataId: string): Promise<string> {
    return await this.orchestrator.delete(dataId);
  }

  @Post('save-to-couch')
  @ApiBody({
    schema: {
      type: 'array',
      items: {
        type: 'object',
      },
    },
  })
  @Public(true)
  // @UseGuards(OtpAuthGuard)
  async saveToCouch(@Body() body: any[]) {
    try {
      await this.orchestrator.saveTransactionToCouch(body);
      return {
        message: 'Success',
      };
    } catch (error) {
      throw new BadRequestException({
        message: error.message,
        error: error.stack,
      });
    }
  }
}
