import { Body, Controller, Get, Header, HttpCode, HttpStatus, Post, Req, Res } from '@nestjs/common';
import { ReportsService } from './reports.service';
import { Roles } from 'src/roles/roles.decorator';
import { ERole } from 'src/roles/roles.service';
import RequestWithUser from '../common/interfaces/requestWithUser.interface';
import { TableReportDto } from './dto/table-report.dto';
import { CsvReportDto } from './dto/csv-report.dto';
import { write } from '@fast-csv/format';
import { Response } from 'express';

@Controller('report')
export class ReportsController {
  constructor(
    private reportsService: ReportsService,
  ) {}

  @Get('years')
  @HttpCode(HttpStatus.OK)
  @Roles(
    // user_class_id = 1
    ERole.SystemDeveloper,
    ERole.IPWAdministrator,
    ERole.IPWAuditor,
    ERole.IPWDataCapturer,
    ERole.IPWContentManager,
    ERole.IPWLeadAuditor,
    ERole.MemberAdministrator, // 2
    ERole.EditEvaluationForms, // 2
    ERole.MemberReports,
    ERole.ViewEvaluationForms, // 2
    ERole.ViewStatusOnly, // 2
  )
  async years() {
    const data = await this.reportsService.findYears();
    return { data };
  }

  @Get('group-names')
  @HttpCode(HttpStatus.OK)
  @Roles(
    // user_class_id = 1
    ERole.SystemDeveloper,
    ERole.IPWAdministrator,
    ERole.IPWAuditor,
    ERole.IPWDataCapturer,
    ERole.IPWContentManager,
    ERole.IPWLeadAuditor,
    ERole.MemberAdministrator, // 2
    ERole.EditEvaluationForms, // 2
    ERole.MemberReports,
    ERole.ViewEvaluationForms, // 2
    ERole.ViewStatusOnly, // 2
  )
  async groupNames(
    @Req() req: RequestWithUser
  ) {
    const data = await this.reportsService.findGroupNames(req.user.user_id);
    return { data };
  }

  @Get('control-products')
  @HttpCode(HttpStatus.OK)
  @Roles(
    // user_class_id = 1
    ERole.SystemDeveloper,
    ERole.IPWAdministrator,
    ERole.IPWAuditor,
    ERole.IPWDataCapturer,
    ERole.IPWContentManager,
    ERole.IPWLeadAuditor,
    ERole.MemberAdministrator, // 2
    ERole.EditEvaluationForms, // 2
    ERole.MemberReports,
    ERole.ViewEvaluationForms, // 2
    ERole.ViewStatusOnly, // 2
  )
  async controlProducts(
    @Req() req: RequestWithUser
  ) {
    const data = await this.reportsService.findControlProducts(req.user.user_id);
    return { data };
  }

  @Post('table-report')
  @HttpCode(HttpStatus.OK)
  @Roles(
    // user_class_id = 1
    ERole.SystemDeveloper,
    ERole.IPWAdministrator,
    ERole.IPWAuditor,
    ERole.IPWDataCapturer,
    ERole.IPWContentManager,
    ERole.IPWLeadAuditor,
    ERole.MemberAdministrator, // 2
    ERole.EditEvaluationForms, // 2
    ERole.MemberReports,
    ERole.ViewEvaluationForms, // 2
    ERole.ViewStatusOnly, // 2
  )
  async tableReport(
    @Req() req: RequestWithUser,
    @Body() body: TableReportDto
  ) {
    const data = await this.reportsService.getTableReport(
      req.user.user_id,
      body.year,
      body.user_group_id,
      body.control_product_id
    );
    return { data };
  }

  @Post('csv-report')
  @HttpCode(HttpStatus.OK)
  @Roles(
    // user_class_id = 1
    ERole.SystemDeveloper,
    ERole.IPWAdministrator,
    ERole.IPWAuditor,
    ERole.IPWDataCapturer,
    ERole.IPWContentManager,
    ERole.IPWLeadAuditor,
    ERole.MemberAdministrator, // 2
    ERole.EditEvaluationForms, // 2
    ERole.MemberReports,
    ERole.ViewEvaluationForms, // 2
    ERole.ViewStatusOnly, // 2
  )
  async csvReport(
    @Req() req: RequestWithUser,
    @Body() body: CsvReportDto,
    @Res() res: Response
  ) {
    // Get the report data
    const data = await this.reportsService.getTableReport(
      req.user.user_id,
      body.year,
      body.user_group_id,
      body.control_product_id
    );

    // Define the csv header
    const headers = []
    switch (body.locale) {
      case 'en':
        if (body.user_group_id === -1) headers.push('Group')
        headers.push('Product Group', 'Trade Name', 'Active Ingredient' ,'Formulation')
      break;
      case 'afr':
        if (body.user_group_id === -1) headers.push('Groep')
        headers.push('Produk Groep', 'Handelsnaam', 'Aktiewe Bestanddeel' ,'Formulering')
      break;
    }

    // Stores the CSV data
    const rows: string[][] = [headers];

    // Convert object to array
    for (let i = 0, n = data.length; i < n; i++) {
      rows.push(Object.values(data[i]) as string[])
    }

    // https://notiz.dev/blog/type-safe-file-downloads#preview-or-download-file
    // https://c2fo.github.io/fast-csv/docs/formatting/methods/#write
    res.contentType('text/csv')
    // This never reaches the front-end for some reason, also tried res.set (http://expressjs.com/en/api.html#res.set)
    // and @Header (https://docs.nestjs.com/techniques/streaming-files) but there is no effect
    res.attachment(`ipw_member_report_${(new Date().toJSON().slice(0,10))}.csv`);
    const file = write(rows);
    res.send(file);
  }
}