import {
  Body,
  Controller,
  Get,
  Injectable,
  Param,
  Post,
  Query,
  UnprocessableEntityException,
} from '@nestjs/common';
import { ApiQuery, ApiTags } from '@nestjs/swagger';
import { Public } from 'src/core/guards';
import { MidtransService } from '../data/services/midtrans.service';
import { EventBus } from '@nestjs/cqrs';
import {
  MidtransCallbackEvent,
  MidtransStatus,
} from '../domain/entities/midtrans-callback.event';
import { MidtransDto } from './dto/midtrans.dto';

@ApiTags(`midtrans`)
@Controller('v1/midtrans')
@Public()
@Injectable()
export class MidtransController {
  constructor(
    private dataService: MidtransService,
    private eventBus: EventBus,
  ) {}

  @Get(':id/status')
  async getStatus(@Param('id') id: string) {
    try {
      const data = await this.dataService.getStatus(id);
      this.eventBus.publishAll([
        new MidtransCallbackEvent({
          id: id,
          data: data,
        }),
      ]);

      return 'Berhasil update status transaksi';
    } catch (error) {
      console.log(error.message);
      throw new Error('Gagal update status transaksi');
    }
  }

  @Get('sync')
  async syncStatus() {
    try {
      const results = await this.dataService.syncPendingStatus();

      for (const data of results) {
        this.eventBus.publishAll([
          new MidtransCallbackEvent({
            id: data.order_id,
            data: data,
          }),
        ]);
      }

      return 'Berhasil update status transaksi';
    } catch (error) {
      console.log(error.message);
      throw new Error('Gagal update status transaksi');
    }
  }

  @Get(':id/change-status')
  @ApiQuery({ name: 'status', enum: MidtransStatus })
  async cancel(
    @Param('id') id: string,
    @Query('status') status = MidtransStatus.cancel,
  ) {
    try {
      return await this.dataService.changeStatus(id, status);
    } catch (error) {
      const data =
        error.ApiResponse?.status_message ??
        error.message ??
        'Gagal update status transaksi';
      throw new UnprocessableEntityException(data);
    }
  }

  @Post('callback')
  async callback(@Body() callback: MidtransDto) {
    const data = await this.dataService.getStatus(callback?.order_id);
    this.eventBus.publishAll([
      new MidtransCallbackEvent({
        id: data.order_id,
        data: data,
      }),
    ]);
    console.log(`midtrans callback for order ${data.order_id}`);
    return 'success listen callback';
  }
}
