import {
  Controller,
  Get,
  Query,
  Req,
  UseGuards,
  Res,
  Post,
  UseInterceptors,
  UploadedFile,
} from "@nestjs/common"
import { FileInterceptor } from "@nestjs/platform-express"
import { ApiConsumes, ApiBody } from "@nestjs/swagger"
import { ReportsService } from "./reports.service"
import { ApiBearerAuth, ApiTags } from "@nestjs/swagger"
import { AuthGuardMiddleware } from "../../middleware/auth-guard.middleware"
import { ProjectReportFiltersDto } from "./dto/project-report-filters.dto"
import { TimeEntriesReportFiltersDto } from "./dto/time-entries-report-filters.dto"
import { ProjectCostingFiltersDto } from "./dto/project-costing-filters.dto"
import { ProjectAnalyticsFiltersDto } from "./dto/project-analytics-filters.dto"
import { EmployeeProductivityFiltersDto } from "./dto/employee-productivity-filters.dto"
import { TimesheetReportFiltersDto } from "./dto/timesheet-report-filters.dto"
import { ClockInReportFiltersDto } from "./dto/clock-in-report-filters.dto"
import { ClockInReportExportDto } from "./dto/clock-in-report.dto"
import { ProjectReportExportDto } from "./dto/export-filters.dto"
import { Response } from "express"
import { DashboardResponseDto } from "./dto/dashboard-response.dto"
import { LeaveAnalyticsFiltersDto } from "./dto/leave-analytics-filters.dto"
import { ProjectManagementFiltersDto } from "./dto/project-management-filters.dto"

@Controller("reports")
@ApiBearerAuth("access-token")
@ApiTags("Reports")
@UseGuards(AuthGuardMiddleware)
export class ReportsController {
  constructor(private readonly reportsService: ReportsService) {}

  @Get("dashboard")
  getDashboard(@Req() request: Request): Promise<DashboardResponseDto> {
    return this.reportsService.getDashboard(request.headers["authorization"])
  }

  @Get("dashboard/activity-percentage")
  getActivityPercentage(
    @Query() filters: ProjectAnalyticsFiltersDto,
    @Req() request: Request,
  ) {
    return this.reportsService.getActivityPercentage(
      filters,
      request.headers["authorization"],
    )
  }

  @Get("employee-productivity")
  getEmployeeProductivity(
    @Query() filters: EmployeeProductivityFiltersDto,
    @Req() request: Request,
  ) {
    return this.reportsService.getEmployeeProductivity(
      filters,
      request.headers["authorization"],
    )
  }

  @Get("dashboard/project-analytics")
  getProjectAnalytics(
    @Query() filters: ProjectAnalyticsFiltersDto,
    @Req() request: Request,
  ) {
    return this.reportsService.getProjectAnalytics(
      filters,
      request.headers["authorization"],
    )
  }

  @Get("dashboard/leave-analytics")
  getLeaveAnalytics(
    @Query() filters: LeaveAnalyticsFiltersDto,
    @Req() request: Request,
  ) {
    return this.reportsService.getLeaveAnalytics(
      filters,
      request.headers["authorization"],
    )
  }

  @Get("project")
  getProjectReport(
    @Query() filters: ProjectReportFiltersDto,
    @Req() request: Request,
  ) {
    return this.reportsService.getProjectReport(
      filters,
      request.headers["authorization"],
    )
  }

  @Get("time-entries")
  getTimeEntriesReport(
    @Query() filters: TimeEntriesReportFiltersDto,
    @Req() request: Request,
  ) {
    return this.reportsService.getTimeEntriesReport(
      filters,
      request.headers["authorization"],
    )
  }

  @Get("project-costing")
  getProjectCostingReport(
    @Query() filters: ProjectCostingFiltersDto,
    @Req() request: Request,
  ) {
    return this.reportsService.getProjectCostingReport(
      filters,
      request.headers["authorization"],
    )
  }

  @Get("project-costing-list")
  getProjectCostingList(
    @Query() filters: ProjectCostingFiltersDto,
    @Req() request: Request,
  ) {
    return this.reportsService.getProjectCostingList(
      filters,
      request.headers["authorization"],
    )
  }

  @Get("timesheet")
  getTimesheetReport(
    @Query() filters: TimesheetReportFiltersDto,
    @Req() request: Request,
  ) {
    return this.reportsService.getTimesheetReport(
      filters,
      request.headers["authorization"],
    )
  }

  @Get("clock-in")
  getClockInReport(
    @Query() filters: ClockInReportFiltersDto,
    @Req() request: Request,
  ) {
    return this.reportsService.getClockInReport(
      filters,
      request.headers["authorization"],
    )
  }

  @Get("project-management")
  getProjectManagementReport(
    @Query() filters: ProjectManagementFiltersDto,
    @Req() request: Request,
  ) {
    return this.reportsService.getProjectManagementReport(
      filters,
      request.headers["authorization"],
    )
  }

  @Get("export/project")
  async exportProjectReport(
    @Query() filters: ProjectReportExportDto,
    @Req() request: Request,
    @Res() res: Response,
  ) {
    return this.reportsService.exportProjectReport(
      res,
      filters,
      request.headers["authorization"],
    )
  }

  @Get("export/clock-in")
  async exportClockInReport(
    @Query() filters: ClockInReportExportDto,
    @Req() request: Request,
    @Res() res: Response,
  ) {
    return this.reportsService.exportClockInReport(
      res,
      filters,
      request.headers["authorization"],
    )
  }

  @Get("export/timesheet")
  async exportTimesheetReport(
    @Query() filters: TimesheetReportFiltersDto,
    @Req() request: Request,
    @Res() res: Response,
  ) {
    return this.reportsService.exportTimesheetReport(
      res,
      filters,
      request.headers["authorization"],
    )
  }

  @Get("export/project-costing-list")
  async exportProjectCostingList(
    @Query() filters: ProjectCostingFiltersDto,
    @Req() request: Request,
    @Res() res: Response,
  ) {
    return this.reportsService.exportProjectCostingList(
      res,
      filters,
      request.headers["authorization"],
    )
  }

  @Get("export/project-costing-report")
  async exportProjectCostingReport(
    @Query() filters: ProjectCostingFiltersDto,
    @Req() request: Request,
    @Res() res: Response,
  ) {
    return this.reportsService.exportProjectCostingReport(
      res,
      filters,
      request.headers["authorization"],
    )
  }

  @Post("timesheet/bulk-upload")
  @UseInterceptors(FileInterceptor("file"))
  @ApiConsumes("multipart/form-data")
  @ApiBody({
    description: "Excel file for bulk timesheet upload",
    schema: {
      type: "object",
      properties: {
        file: {
          type: "string",
          format: "binary",
          description:
            "Excel file (.xlsx) containing timesheet data with NOTE row, headers, and data rows. Required columns: project_name, employee_email, start_time, end_time, activity_type, description",
        },
      },
      required: ["file"],
    },
  })
  async bulkUploadTimesheets(
    @UploadedFile() file: Express.Multer.File,
    @Req() request: Request,
  ) {
    if (!file) {
      return {
        success: false,
        message: "Excel file is required",
        code: 400,
      }
    }

    if (!file.originalname.match(/\.(xlsx)$/)) {
      return {
        success: false,
        message: "Only Excel files (.xlsx) are allowed",
        code: 400,
      }
    }

    const result = await this.reportsService.bulkUploadTimesheets(
      file.buffer,
      request.headers["authorization"],
    )

    // Always return JSON response, but include error file as base64 if there are errors
    if (
      result.success &&
      (result as any).data?.error_file &&
      (result as any).data.errors?.length > 0
    ) {
      const timestamp = new Date().toISOString().replace(/[:.]/g, "-")
      const filename = `timesheet-upload-errors-${timestamp}.xlsx`

      // Convert buffer to base64 for JSON response
      const errorFileBase64 = (result as any).data.error_file.toString("base64")

      return {
        ...result,
        data: {
          ...(result as any).data,
          error_file_name: filename,
          error_file_base64: errorFileBase64,
          // Remove the buffer from response to avoid circular reference
          error_file: undefined,
        },
      }
    }

    // Return normal JSON response if no errors
    return result
  }
}
