import {
  Controller,
  Get,
  Post,
  Param,
  Body,
  Res,
  HttpException,
  HttpStatus,
} from '@nestjs/common';
import { Public } from '../auth/public.decorator';
import { Response } from 'express';
import { ReportsHistoryService } from './reports_history.service';
import {
  ApiBearerAuth,
  ApiTags,
  ApiBody,
  ApiParam,
  ApiQuery,
  ApiOperation,
} from '@nestjs/swagger';

@ApiTags('reports')
@ApiBearerAuth('access-token')
@Controller('reports')
export class ReportsHistoryController {
  constructor(private readonly reportsHistoryService: ReportsHistoryService) {}

  @Public()
  @Get('history')
  @ApiOperation({ summary: 'Get Reports History' })
  async getReportsHistory() {
    try {
      const result = await this.reportsHistoryService.getAllReports();
      if (!result.success) {
        throw new HttpException((result as any).error, HttpStatus.BAD_REQUEST);
      }
      return result;
    } catch (error: any) {
      throw new HttpException(error.message, HttpStatus.INTERNAL_SERVER_ERROR);
    }
  }

  @Public()
  @Post('generate')
  @ApiOperation({ summary: 'Generate Report' })
  @ApiBody({
    schema: {
      type: 'object',
      properties: {
        type: { type: 'string' },
        dateRange: { type: 'string', example: '2023-01-01 to 2023-12-31' },
        createdBy: { type: 'number' },
        franchiseId: { type: 'number' },
      },
      required: ['type', 'createdBy', 'franchiseId'],
    },
  })
  async generateReport(
    @Body()
    body: {
      type: string;
      dateRange?: string;
      createdBy: number;
      franchiseId: number; // Make franchiseId required
    },
  ) {
    try {
      // Parse date range if provided
      let dateRange = null;
      if (body.dateRange) {
        const dates = body.dateRange.split(' to ');
        if (dates.length === 2) {
          dateRange = {
            start: new Date(dates[0]),
            end: new Date(dates[1]),
          };
        }
      }

      const result = (await this.reportsHistoryService.generateReport({
        type: body.type,
        dateRange: dateRange || { start: new Date(), end: new Date() },
        createdBy: body.createdBy,
        franchiseId: body.franchiseId,
      })) as any;

      if (!result.success) {
        throw new HttpException((result as any).error, HttpStatus.BAD_REQUEST);
      }
      return result;
    } catch (error: any) {
      throw new HttpException(error.message, HttpStatus.INTERNAL_SERVER_ERROR);
    }
  }

  @Public()
  @Get('download/:id')
  @ApiOperation({ summary: 'Download Report' })
  @ApiParam({ name: 'id', type: String })
  @ApiBody({
    schema: { type: 'object', properties: { franchiseId: { type: 'number' } } },
  })
  async downloadReport(
    @Param('id') id: string,
    @Body() body: { franchiseId?: number },
    @Res() res: Response,
  ) {
    try {
      const result = await this.reportsHistoryService.downloadReport(
        parseInt(id),
        body.franchiseId,
      );

      if (!result.success) {
        throw new HttpException(result.error, HttpStatus.NOT_FOUND);
      }

      res.setHeader('Content-Type', result.data.contentType);
      res.setHeader(
        'Content-Disposition',
        `attachment; filename="${result.data.filename}"`,
      );
      res.send(result.data.fileBuffer);
    } catch (error: any) {
      throw new HttpException(error.message, HttpStatus.INTERNAL_SERVER_ERROR);
    }
  }

  @Public()
  @Post('email')
  @ApiOperation({ summary: 'Email Report' })
  @ApiBody({
    schema: {
      type: 'object',
      properties: {
        reportId: { type: 'number' },
        email: { type: 'string', format: 'email' },
        franchiseId: { type: 'number' },
      },
      required: ['reportId', 'email'],
    },
  })
  async emailReport(
    @Body() body: { reportId: number; email: string; franchiseId?: number },
  ) {
    try {
      const result = await this.reportsHistoryService.emailReport({
        reportId: body.reportId,
        email: body.email,
        franchiseId: body.franchiseId,
      });

      if (!result.success) {
        throw new HttpException((result as any).error, HttpStatus.BAD_REQUEST);
      }
      return result;
    } catch (error: any) {
      throw new HttpException(error.message, HttpStatus.INTERNAL_SERVER_ERROR);
    }
  }

  @Public()
  @Get(':id')
  @ApiOperation({ summary: 'Get Report By ID' })
  @ApiParam({ name: 'id', type: String })
  @ApiBody({
    schema: { type: 'object', properties: { franchiseId: { type: 'number' } } },
  })
  async getReportById(
    @Param('id') id: string,
    @Body() body: { franchiseId?: number },
  ) {
    try {
      const result = await this.reportsHistoryService.getReportById(
        parseInt(id),
        body.franchiseId,
      );

      if (!result.success) {
        throw new HttpException(result.error, HttpStatus.NOT_FOUND);
      }
      return result;
    } catch (error: any) {
      throw new HttpException(error.message, HttpStatus.INTERNAL_SERVER_ERROR);
    }
  }
}
