import {
  Controller,
  Get,
  Post,
  Body,
  Patch,
  Param,
  Delete,
  UseInterceptors,
  UploadedFile,
  Res,
  HttpStatus,
  Query,
  NotFoundException,
  BadRequestException,
  ConflictException,
  UseGuards,
} from '@nestjs/common';
import { SponsorsService } from './sponsors.service';
import { CreateSponsorDto } from './dto/create-sponsor.dto';
import { UpdateSponsorDto } from './dto/update-sponsor.dto';
import { FileInterceptor } from '@nestjs/platform-express';
import { sponsorImageConfig } from 'src/common/file upload/multer-config';
import { Response as ExpressResponse } from 'express';
import {
  errorResponse,
  successResponse,
} from 'src/common/errors/response-config';
import { lan } from 'src/lan';
import { saveError } from 'src/api-logs/api-error-log';
import { InjectRepository } from '@nestjs/typeorm';
import { ApiLog } from 'src/api-logs/entities/api-log.entity';
import { DataSource, Repository } from 'typeorm';
import isValidUuidV4 from 'src/common/uuid validator/uuid-validate';
import { commonMessage } from 'src/common/messages';
import { isEmpty } from 'src/common/helper';
import { AuthGuardMiddleware } from 'src/common/middleware/auth.middleware';

@Controller('sponsors')
export class SponsorsController {
  constructor(
    private readonly sponsorsService: SponsorsService,
    @InjectRepository(ApiLog)
    private readonly apiLogRepository: Repository<ApiLog>,
    private readonly connection: DataSource,
  ) {}

  @Post('add')
  @UseGuards(AuthGuardMiddleware)
  @UseInterceptors(FileInterceptor('image', sponsorImageConfig))
  async create(
    @UploadedFile() file: Express.Multer.File,
    @Body() createSponsorDto: CreateSponsorDto,
    @Res() res: ExpressResponse,
  ) {
    try {
      const sponsor = await this.sponsorsService.create({
        ...createSponsorDto,
        image: file?.filename,
      });

      res.send(successResponse(201, lan('common.request_submitted'), sponsor));
    } catch (error) {
      saveError(error, this.apiLogRepository);

      res
        .status(HttpStatus.INTERNAL_SERVER_ERROR)
        .send(errorResponse(500, lan('common.internal_server_error'), error));
    }
  }

  @Get('get')
  async findAll(
    @Query('take') take: number,
    @Query('skip') skip: number,
    @Query('search') search: string,
    @Res() res: ExpressResponse,
  ) {
    try {
      const sponsor = await this.sponsorsService.findAll(take, skip, search);
      res
        .status(HttpStatus.OK)
        .send(
          successResponse(
            200,
            lan('common.data_retrieved_successfully'),
            sponsor,
          ),
        );
    } catch (error) {
      saveError(error, this.apiLogRepository);

      res
        .status(HttpStatus.INTERNAL_SERVER_ERROR)
        .send(errorResponse(500, lan('common.internal_server_error'), error));
    }
  }

  @Get('get/:id')
  async findOne(@Param('id') id: string, @Res() res: ExpressResponse) {
    try {
      const sponsor = await this.sponsorsService.findOne(id);
      res
        .status(HttpStatus.OK)
        .send(
          successResponse(
            200,
            lan('common.data_retrieved_successfully'),
            sponsor,
          ),
        );
    } catch (error) {
      saveError(error, this.apiLogRepository);

      res
        .status(HttpStatus.INTERNAL_SERVER_ERROR)
        .send(errorResponse(500, lan('common.internal_server_error'), error));
    }
  }

  @Patch('update/:id')
  @UseGuards(AuthGuardMiddleware)
  @UseInterceptors(FileInterceptor('image', sponsorImageConfig))
  async update(
    @Param('id') id: string,
    @UploadedFile() attachment,
    @Body() updateSponsorDto: UpdateSponsorDto,
    @Res() res: ExpressResponse,
  ) {
    try {
      if (!isValidUuidV4(id)) {
        const errorMessage = commonMessage.invalidUuidFormat.replace('#id', id);
        res.send(errorResponse(400, errorMessage));
        return;
      }

      const data = await this.sponsorsService.findOne(id);

      if (isEmpty(data)) {
        return res.send(errorResponse(404, lan('common.data_not_found')));
      }

      if (data) {
        if (attachment) {
          const attachmentUrl = `uploads/sponsor-image/${attachment.filename}`;
          updateSponsorDto.image = attachmentUrl;
        }

        await this.sponsorsService.update(id, updateSponsorDto);
      }

      res.send(successResponse(200, lan('common.data_updated')));
    } catch (error) {
      saveError(error, this.apiLogRepository);

      res
        .status(500)
        .send(errorResponse(500, lan('common.internal_server_error')));
    }
  }

  @Delete('delete/:id')
  @UseGuards(AuthGuardMiddleware)
  async remove(@Param('id') id: string, @Res() res: ExpressResponse) {
    try {
      const sponsor = await this.sponsorsService.remove(id);

      res
        .status(HttpStatus.OK)
        .send(successResponse(200, lan('common.data_deleted'), sponsor));
    } catch (error) {
      saveError(error, this.apiLogRepository);

      if (
        error instanceof NotFoundException ||
        error instanceof BadRequestException
      ) {
        res
          .status(HttpStatus.NOT_FOUND)
          .send(errorResponse(404, error.message));
      } else {
        res
          .status(HttpStatus.INTERNAL_SERVER_ERROR)
          .send(errorResponse(500, lan('common.internal_server_error'), error));
      }
    }
  }
}
