import { Controller, Get, Logger, Post, Req, Res } from '@nestjs/common'

import { FastifyReply, FastifyRequest } from 'fastify'

import { DataManagementService } from './data-management.service'

@Controller('data-management')
export class DataManagementController {
  private readonly logger = new Logger(DataManagementController.name)

  constructor(private readonly dataManagementService: DataManagementService) {}

  // ============================================================================
  // Export Endpoints
  // ============================================================================

  @Post('export-raw-excel')
  async exportRawExcel(@Req() req: FastifyRequest, @Res({ passthrough: true }) res: FastifyReply): Promise<void> {
    try {
      const data = await req.file()
      if (!data) {
        throw new Error('No file uploaded')
      }
      const fileBuffer = await data.toBuffer()
      const { filename, data: exportData } = await this.dataManagementService.exportRawExcel(fileBuffer)

      const json = JSON.stringify(exportData, null, 2)

      res.type('application/json')
      res.header('Content-Disposition', `attachment; filename="${filename}"`)
      res.header('Access-Control-Expose-Headers', 'Content-Disposition')
      res.send(json)
    } catch (error) {
      this.logger.error('Error exporting raw Excel data', error)
      res.status(500).send({ error: error instanceof Error ? error.message : String(error) })
    }
  }

  @Post('export-processed-excel')
  async exportProcessedExcel(@Req() req: FastifyRequest, @Res({ passthrough: true }) res: FastifyReply): Promise<void> {
    try {
      const data = await req.file()
      if (!data) {
        throw new Error('No file uploaded')
      }
      const fileBuffer = await data.toBuffer()
      const { filename, data: exportData } = await this.dataManagementService.exportProcessedExcel(fileBuffer)

      const json = JSON.stringify(exportData, null, 2)

      res.type('application/json')
      res.header('Content-Disposition', `attachment; filename="${filename}"`)
      res.header('Access-Control-Expose-Headers', 'Content-Disposition')
      res.send(json)
    } catch (error) {
      this.logger.error('Error exporting processed Excel data', error)
      res.status(500).send({ error: error instanceof Error ? error.message : String(error) })
    }
  }

  @Get('export-database-excel-format')
  async exportDatabaseExcelFormat(@Res({ passthrough: true }) res: FastifyReply): Promise<void> {
    try {
      const { filename, data } = await this.dataManagementService.exportDatabaseExcelFormat()

      const json = JSON.stringify(data, null, 2)

      res.type('application/json')
      res.header('Content-Disposition', `attachment; filename="${filename}"`)
      res.header('Access-Control-Expose-Headers', 'Content-Disposition')
      res.send(json)
    } catch (error) {
      this.logger.error('Error exporting database to Excel format', error)
      res.status(500).send({ error: error instanceof Error ? error.message : String(error) })
    }
  }

  @Get('export-database-json-format')
  async exportDatabaseJsonFormat(@Res({ passthrough: true }) res: FastifyReply): Promise<void> {
    try {
      const { filename, data } = await this.dataManagementService.exportDatabaseJsonFormat()

      const json = JSON.stringify(data, null, 2)

      res.type('application/json')
      res.header('Content-Disposition', `attachment; filename="${filename}"`)
      res.header('Access-Control-Expose-Headers', 'Content-Disposition')
      res.send(json)
    } catch (error) {
      this.logger.error('Error exporting database to JSON format', error)
      res.status(500).send({ error: error instanceof Error ? error.message : String(error) })
    }
  }

  // ============================================================================
  // Seed Endpoints (Clear DB + Import)
  // ============================================================================

  @Post('seed-from-raw-excel')
  async seedFromRawExcel(@Req() req: FastifyRequest, @Res({ passthrough: true }) res: FastifyReply): Promise<any> {
    try {
      const data = await req.file()
      if (!data) {
        throw new Error('No file uploaded')
      }
      const fileBuffer = await data.toBuffer()
      const result = await this.dataManagementService.seedFromRawExcel(fileBuffer, data.filename)
      res.status(200).send(result)
    } catch (error) {
      this.logger.error('Error seeding from raw Excel data', error)
      res.status(500).send({ success: false, error: error instanceof Error ? error.message : String(error) })
    }
  }

  @Post('seed-from-decoded-json')
  async seedFromDecodedJson(@Req() req: FastifyRequest, @Res({ passthrough: true }) res: FastifyReply): Promise<any> {
    try {
      const data = await req.file()
      if (!data) {
        throw new Error('No file uploaded')
      }
      const fileBuffer = await data.toBuffer()
      const result = await this.dataManagementService.seedFromDecodedJson(fileBuffer)
      res.status(200).send(result)
    } catch (error) {
      this.logger.error('Error seeding from decoded JSON', error)
      res.status(500).send({ success: false, error: error instanceof Error ? error.message : String(error) })
    }
  }

  @Post('seed-from-excel-formatted-json')
  async seedFromExcelFormattedJson(
    @Req() req: FastifyRequest,
    @Res({ passthrough: true }) res: FastifyReply,
  ): Promise<any> {
    try {
      const data = await req.file()
      if (!data) {
        throw new Error('No file uploaded')
      }
      const fileBuffer = await data.toBuffer()
      const result = await this.dataManagementService.seedFromExcelFormattedJson(fileBuffer)
      res.status(200).send(result)
    } catch (error) {
      this.logger.error('Error seeding from Excel-formatted JSON', error)
      res.status(500).send({ success: false, error: error instanceof Error ? error.message : String(error) })
    }
  }

  @Post('seed-from-json-formatted-json')
  async seedFromJsonFormattedJson(
    @Req() req: FastifyRequest,
    @Res({ passthrough: true }) res: FastifyReply,
  ): Promise<any> {
    try {
      const data = await req.file()
      if (!data) {
        throw new Error('No file uploaded')
      }
      const fileBuffer = await data.toBuffer()
      const result = await this.dataManagementService.seedFromJsonFormattedJson(fileBuffer)
      res.status(200).send(result)
    } catch (error) {
      this.logger.error('Error seeding from JSON-formatted JSON', error)
      res.status(500).send({ success: false, error: error instanceof Error ? error.message : String(error) })
    }
  }

  // ============================================================================
  // Update Endpoints (Delta Detection + Import)
  // ============================================================================

  @Post('update-from-raw-excel')
  async updateFromRawExcel(@Req() req: FastifyRequest, @Res({ passthrough: true }) res: FastifyReply): Promise<any> {
    try {
      const data = await req.file()
      if (!data) {
        throw new Error('No file uploaded')
      }
      const fileBuffer = await data.toBuffer()
      const result = await this.dataManagementService.updateFromRawExcel(fileBuffer, data.filename)
      res.status(200).send(result)
    } catch (error) {
      this.logger.error('Error updating from raw Excel data', error)
      res.status(500).send({ success: false, error: error instanceof Error ? error.message : String(error) })
    }
  }

  @Post('update-from-decoded-json')
  async updateFromDecodedJson(@Req() req: FastifyRequest, @Res({ passthrough: true }) res: FastifyReply): Promise<any> {
    try {
      const data = await req.file()
      if (!data) {
        throw new Error('No file uploaded')
      }
      const fileBuffer = await data.toBuffer()
      const result = await this.dataManagementService.updateFromDecodedJson(fileBuffer)
      res.status(200).send(result)
    } catch (error) {
      this.logger.error('Error updating from decoded JSON', error)
      res.status(500).send({ success: false, error: error instanceof Error ? error.message : String(error) })
    }
  }

  @Post('update-from-excel-formatted-json')
  async updateFromExcelFormattedJson(
    @Req() req: FastifyRequest,
    @Res({ passthrough: true }) res: FastifyReply,
  ): Promise<any> {
    try {
      const data = await req.file()
      if (!data) {
        throw new Error('No file uploaded')
      }
      const fileBuffer = await data.toBuffer()
      const result = await this.dataManagementService.updateFromExcelFormattedJson(fileBuffer)
      res.status(200).send(result)
    } catch (error) {
      this.logger.error('Error updating from Excel-formatted JSON', error)
      res.status(500).send({ success: false, error: error instanceof Error ? error.message : String(error) })
    }
  }

  @Post('update-from-json-formatted-json')
  async updateFromJsonFormattedJson(
    @Req() req: FastifyRequest,
    @Res({ passthrough: true }) res: FastifyReply,
  ): Promise<any> {
    try {
      const data = await req.file()
      if (!data) {
        throw new Error('No file uploaded')
      }
      const fileBuffer = await data.toBuffer()
      const result = await this.dataManagementService.updateFromJsonFormattedJson(fileBuffer)
      res.status(200).send(result)
    } catch (error) {
      this.logger.error('Error updating from JSON-formatted JSON', error)
      res.status(500).send({ success: false, error: error instanceof Error ? error.message : String(error) })
    }
  }
}
