import {
  Body,
  Controller,
  Get,
  HttpCode,
  HttpStatus,
  Param,
  Patch,
  Post,
  Query,
  Req,
  Res,
  UseGuards
} from '@nestjs/common';
import { AuthGuard } from '@nestjs/passport';
import { ApiBearerAuth, ApiOperation, ApiTags } from '@nestjs/swagger';
import { Response } from 'express';
import { Roles } from 'src/auth/decorators/roles.decorator';
import { RolesGuard } from 'src/auth/guards/roles.guard';
import { BootstrapTableRequestDto } from 'src/commons/dto/bootstrap-table-request.dto';
import { ExportService } from 'src/export/export.service';
import { ExportQueryDto } from 'src/export/export.types';
import { exportFilename } from 'src/export/export.utils';
import { TRANSACTION_COLUMNS, formatTransactionRows } from '../export/formatters/transaction.formatter';
import { CancelTransactionDto } from './dto/cancel-transaction.dto';
import { CreatePaymentDto } from './dto/create-payment.dto';
import { CreateTransactionDto } from './dto/create-transaction.dto';
import { TransactionChartQueryDto } from './dto/transaction-chart-query.dto';
import { TransactionPerformanceQueryDto } from './dto/transaction-performance-query.dto';
import { TransactionSummaryQueryDto } from './dto/transaction-summary-query.dto';
import { UpdateTransactionDto } from './dto/update-transaction.dto';
import { TransactionsService } from './transactions.service';


@ApiTags('Transactions')
@ApiBearerAuth()
@Controller('transactions')
@UseGuards(AuthGuard('jwt'), RolesGuard)
export class TransactionsController {
  constructor(
    private readonly transactionsService: TransactionsService,
    private readonly exportService: ExportService,
  ) { }

  @Post('generate-item-id')
  @Roles('SUPER_ADMIN', 'HEAD_OPS', 'FRONTLINER', 'HEAD_STORE')
  @HttpCode(HttpStatus.CREATED)
  async generateItemId() {
    const data = await this.transactionsService.generateItemId();

    return {
      message: 'Item ID generated successfully',
      data,
    };
  }

  @Post()
  @Roles('SUPER_ADMIN', 'HEAD_OPS', 'FRONTLINER', 'HEAD_STORE')
  @HttpCode(HttpStatus.CREATED)
  async create(@Req() req, @Body() dto: CreateTransactionDto) {
    const data = await this.transactionsService.create(dto, req.user)
    return {
      message: 'Transaction created successfully',
      data,
    }
  }

  @Get('summary')
  @Roles('SUPER_ADMIN', 'HEAD_FINANCE', 'ADMIN_FINANCE', 'HEAD_STORE', 'HEAD_OPS', 'FRONTLINER', 'STAKEHOLDERS')
  async getSummary(@Query('filter') filter?: { branchId?: string }) {
    const data = await this.transactionsService.getSummary(filter)
    return { message: 'Transaction summary fetched successfully', data }
  }

  @Get()
  @Roles('SUPER_ADMIN', 'HEAD_FINANCE', 'ADMIN_FINANCE', 'HEAD_STORE', 'HEAD_OPS', 'FRONTLINER', 'STAKEHOLDERS')
  async findAll(
    @Req() req: any,
    @Query() query: BootstrapTableRequestDto) {
    const data = await this.transactionsService.findAll(query, req.user)
    return { message: 'Transactions fetched successfully', data }
  }

  @Get('export')
  @Roles('SUPER_ADMIN', 'HEAD_FINANCE', 'ADMIN_FINANCE', 'FRONTLINER', 'HEAD_STORE', 'STAKEHOLDERS')
  async export(
    @Query() query: ExportQueryDto,
    @Req() req: any,
    @Res() res: Response,
  ) {
    const user = req.user;
    const isAllBranch = user.role?.accessAllBranch === true;

    // Determine branch label for filename
    let branchLabel: string | undefined;

    if (isAllBranch && query.branchId) {
      // Admin filtered to a specific branch — find its name
      const branch = user.branches?.find((b: any) => b.branchId === query.branchId);
      branchLabel = branch?.branch?.name ?? query.branchId;
    } else if (isAllBranch) {
      branchLabel = 'all_branches';
    } else {
      // Restricted user — use their first branch name
      branchLabel = user.branches?.[0]?.branch?.name;
    }

    const transactions = await this.transactionsService.getTransactionsForExport(query, user);

    await this.exportService.export(
      {
        filename: exportFilename('transactions', branchLabel),
        // → transactions_tangerang_20260316.xlsx
        // → transactions_all_branches_20260316.xlsx
        sheetName: 'Transactions',
        columns: TRANSACTION_COLUMNS,
        data: formatTransactionRows(transactions),
        format: query.format,
      },
      res,
    );
  }

  @Get(':id')
  @Roles('SUPER_ADMIN', 'HEAD_FINANCE', 'ADMIN_FINANCE', 'HEAD_STORE', 'HEAD_OPS', 'FRONTLINER', 'STAKEHOLDERS')
  async findOne(@Param('id') id: string) {
    const data = await this.transactionsService.findOne(id)
    return { message: 'Transaction fetched successfully', data }
  }

  @Get(':id/audit-logs')
  @Roles('SUPER_ADMIN', 'HEAD_FINANCE', 'ADMIN_FINANCE', 'HEAD_STORE', 'HEAD_OPS', 'FRONTLINER', 'STAKEHOLDERS')
  async getAuditLogs(@Param('id') id: string, @Query() query: BootstrapTableRequestDto) {
    const data = await this.transactionsService.getAuditLogsForTransaction(id, query);
    return { message: 'Audit logs fetched successfully', data };
  }

  @Patch(':id/complete')
  @Roles('SUPER_ADMIN', 'HEAD_STORE', 'HEAD_OPS')
  async complete(
    @Param('id') id: string,
    @Body() dto: { note: string },
    @Req() req,
  ) {
    const data = await this.transactionsService.complete(id, dto.note, req.user)
    return { message: 'Transaction completed successfully', data }
  }

  @Patch(':id/payment')
  @Roles('FRONTLINER', 'HEAD_FINANCE', 'HEAD_OPS', 'HEAD_STORE', 'SUPER_ADMIN', 'ADMIN_FINANCE')
  async addPayment(
    @Param('id') id: string,
    @Body() dto: CreatePaymentDto,
    @Req() req,
  ) {
    const data = await this.transactionsService.addPayment(id, dto, req.user);
    return { message: 'Payment proof uploaded successfully', data };
  }

  @Patch(':id/cancel')
  @Roles('SUPER_ADMIN', 'HEAD_STORE', 'HEAD_OPS')
  async cancel(@Param('id') id: string, @Body() dto: CancelTransactionDto, @Req() req) {
    const data = await this.transactionsService.cancel(id, dto, req.user)
    return { message: 'Transaction cancelled successfully', data }
  }

  @Patch(':id')
  @Roles('SUPER_ADMIN', 'HEAD_FINANCE', 'HEAD_STORE', 'HEAD_OPS', 'FRONTLINER')
  async update(@Param('id') id: string, @Body() dto: UpdateTransactionDto, @Req() req) {
    const data = await this.transactionsService.update(id, dto, req.user)
    return { message: 'Transaction updated successfully', data }
  }

  @ApiOperation({
    summary: 'Get transaction analytics chart',
    description: 'Returns success and bounce series for chart visualization',
  })
  @Get('analytics/chart')
  @Roles('SUPER_ADMIN', 'HEAD_FINANCE', 'ADMIN_FINANCE', 'HEAD_STORE', 'HEAD_OPS', 'FRONTLINER', 'STAKEHOLDERS')
  async getChart(
    @Query() query: TransactionChartQueryDto, @Req() req
  ) {
    const data = await this.transactionsService.getAnalyticsChart(query, req.user)

    return {
      message: 'Transaction chart analytics fetched successfully',
      data,
    }
  }

  @ApiOperation({
    summary: 'Get transaction analytics chart',
    description: 'Returns success and bounce series for chart visualization',
  })
  @Get('analytics/summary')
  @Roles('SUPER_ADMIN', 'HEAD_FINANCE', 'ADMIN_FINANCE', 'HEAD_STORE', 'HEAD_OPS', 'FRONTLINER', 'STAKEHOLDERS')
  async getAnalyticsSummary(
    @Query() query: TransactionSummaryQueryDto, @Req() req
  ) {
    const data = await this.transactionsService.getAnalyticsSummary(query, req.user)

    return {
      message: 'Transaction analytics summary fetched successfully',
      data,
    }
  }

  @ApiOperation({
    summary: 'Transaction performance summary',
    description: 'Returns performance metrics for all, completed, canceled and rejected transactions'
  })
  @Get('analytics/performance-summary')
  @Roles('SUPER_ADMIN', 'HEAD_FINANCE', 'ADMIN_FINANCE', 'HEAD_STORE', 'HEAD_OPS', 'FRONTLINER', 'STAKEHOLDERS')
  async getPerformanceSummary(
    @Query() query: TransactionPerformanceQueryDto, @Req() req
  ) {
    const data = await this.transactionsService.getPerformanceSummary(query, req.user)

    return {
      message: 'Transaction performance summary fetched successfully',
      data
    }
  }

  @ApiOperation({
    summary: 'Transaction cancellation reasons',
    description: 'Returns distinct cancellation reasons with their counts ordered from most to least'
  })
  @Get('analytics/cancellation-reasons')
  @Roles('SUPER_ADMIN', 'HEAD_FINANCE', 'ADMIN_FINANCE', 'HEAD_STORE', 'HEAD_OPS', 'FRONTLINER', 'STAKEHOLDERS')
  async getCancellationReasons(
    @Query() query: TransactionPerformanceQueryDto, @Req() req
  ) {
    const data = await this.transactionsService.getCancellationReasons(query, req.user)

    return {
      message: 'Transaction cancellation reasons fetched successfully',
      data
    }
  }

  @Get('analytics/performance-chart')
  @Roles('SUPER_ADMIN', 'HEAD_FINANCE', 'ADMIN_FINANCE', 'HEAD_STORE', 'HEAD_OPS', 'FRONTLINER', 'STAKEHOLDERS')
  getPerformanceChart(
    @Query() query: TransactionChartQueryDto, @Req() req
  ) {
    return this.transactionsService.getPerformanceChart(query, req.user)
  }
}