import {
  Body,
  Controller,
  Get,
  HttpException,
  Inject,
  InternalServerErrorException,
  Param,
  ParseIntPipe,
  Post,
  Put,
  Req,
  UploadedFiles,
  UseInterceptors,
} from '@nestjs/common';
import { ClientProxy } from '@nestjs/microservices';
import {
  FileFieldsInterceptor,
  FileInterceptor,
} from '@nestjs/platform-express';
import { Request } from 'express';
import { diskStorage } from 'multer';
import { extname, join } from 'path';
import { firstValueFrom } from 'rxjs';
import * as fs from 'fs';
@Controller('api/customer')
export class CustomerGateWayController {
  constructor(@Inject('CUSTOMER_SERVICE') private client: ClientProxy) {}

  @Get('/get-pending-verification-list')
  async getCustomerPendingVerificationList(@Req() req: Request) {
    try {
      console.log('ok gateway is calling as expected!');
      const protocol = req.protocol;
      const host = req.headers.host;
      const result = await firstValueFrom(
        this.client.send(
          { cmd: 'get_pending_verification_list' },
          { protocol, host },
        ),
      );

      return result;
    } catch (err) {
      console.log(err);
      throw new InternalServerErrorException(
        'Something went wrong when fetching pending verifications!',
      );
    }
  }

  @Get('/get-pending-verification-list/:id')
  async getCustomerPendingVerificationListByCustomerId(
    @Req() req: Request,
    @Param('id', ParseIntPipe) id: number,
  ) {
    try {
      console.log('ok gateway is calling as expected!');
      const protocol = req.protocol;
      const host = req.headers.host;
      const result = await firstValueFrom(
        this.client.send(
          { cmd: 'get_pending_verification_list_by_customer_id' },
          { protocol, host, id },
        ),
      );

      return result;
    } catch (err) {
      console.log(err);
      throw new InternalServerErrorException(
        'Something went wrong when fetching pending verifications!',
      );
    }
  }

  @Get()
  async getAllCustomers(@Req() req: Request) {
    try {
      const protocol = req.protocol;
      const host = req.headers.host;

      return await firstValueFrom(
        this.client.send({ cmd: 'customer_get_all' }, { protocol, host }),
      );
    } catch (err) {
      console.log(err);
      throw new InternalServerErrorException('Something went wrong');
    }
  }

  @Get(':id')
  async getCustomerById(
    @Param('id', ParseIntPipe) id: number,
    @Req() req: Request,
  ) {
    try {
      const protocol = req.protocol;
      const host = req.headers.host;

      return await firstValueFrom(
        this.client.send({ cmd: 'customer_get_by_id' }, { id, protocol, host }),
      );
    } catch (err) {
      console.log(err);
      throw new InternalServerErrorException('Something went wrong');
    }
  }

  @Post()
  @UseInterceptors(
    FileFieldsInterceptor(
      [
        {
          name: 'Salary_Slip',
          maxCount: 1,
        },
        {
          name: 'NIC_Front',
          maxCount: 1,
        },
        {
          name: 'NIC_Back',
          maxCount: 1,
        },
        {
          name: 'Utility_Bill',
          maxCount: 1,
        },
        {
          name: 'Photo',
          maxCount: 1,
        },
      ],
      {
        storage: diskStorage({
          destination: (req, file, cb) => {
            const folder =
              file.fieldname == 'Salary_Slip'
                ? 'customer/salary_slips'
                : file.fieldname == 'NIC_Front'
                  ? 'customer/NIC_Front'
                  : file.fieldname == 'NIC_Back'
                    ? 'customer/NIC_Back'
                    : file.fieldname == 'Utility_Bill'
                      ? 'customer/utility_bills'
                      : 'customer/Photos';
            const folderPath = join(
              __dirname,
              '..',
              '..',
              '..',
              'uploads',
              folder,
            );

            if (!fs.existsSync(folderPath)) {
              fs.mkdirSync(folderPath, { recursive: true });
            }

            cb(null, folderPath);
          },

          filename: (req, file, cb) => {
            const uniqueSuffix =
              Date.now() + '-' + Math.round(Math.random() * 1e9);
            cb(null, `${uniqueSuffix}${extname(file.originalname)}`);
          },
        }),
      },
    ),
  )
  async createCustomer(
    @Body() body: any,
    @UploadedFiles()
    files: {
      Salary_Slip_Path?: Express.Multer.File[];
      NIC_Front_Path?: Express.Multer.File[];
      NIC_Back_Path?: Express.Multer.File[];
      Utility_Bill_Path?: Express.Multer.File[];
      Photo_Path?: Express.Multer.File[];
    },
  ) {
    try {
      console.log('here is calling12');
      const result = await firstValueFrom(
        this.client.send({ cmd: 'customer_create' }, { body, files }),
      );

      return result;
    } catch (err) {
      console.log(err);
      throw new InternalServerErrorException(err);
    }
  }

  @Put(':id')
  @UseInterceptors(
    FileFieldsInterceptor(
      [
        {
          name: 'Salary_Slip',
          maxCount: 1,
        },
        {
          name: 'NIC_Front',
          maxCount: 1,
        },
        {
          name: 'NIC_Back',
          maxCount: 1,
        },
        {
          name: 'Utility_Bill',
          maxCount: 1,
        },
        {
          name: 'Photo',
          maxCount: 1,
        },
      ],
      {
        storage: diskStorage({
          destination: (req, file, cb) => {
            const folder =
              file.fieldname == 'Salary_Slip'
                ? 'customer/salary_slips'
                : file.fieldname == 'NIC_Front'
                  ? 'customer/NIC_Front'
                  : file.fieldname == 'NIC_Back'
                    ? 'customer/NIC_Back'
                    : file.fieldname == 'Utility_Bill'
                      ? 'customer/utility_bills'
                      : 'customer/Photos';
            const folderPath = join(
              __dirname,
              '..',
              '..',
              '..',
              'uploads',
              folder,
            );

            if (!fs.existsSync(folderPath)) {
              fs.mkdirSync(folderPath, { recursive: true });
            }

            cb(null, folderPath);
          },

          filename: (req, file, cb) => {
            const uniqueSuffix =
              Date.now() + '-' + Math.round(Math.random() * 1e9);
            cb(null, `${uniqueSuffix}${extname(file.originalname)}`);
          },
        }),
      },
    ),
  )
  async updateCustomer(
    @Param('id', ParseIntPipe) id: number,
    @Body() body: any,
    @UploadedFiles()
    files: {
      Salary_Slip_Path?: Express.Multer.File[];
      NIC_Front_Path?: Express.Multer.File[];
      NIC_Back_Path?: Express.Multer.File[];
      Utility_Bill_Path?: Express.Multer.File[];
      Photo_Path?: Express.Multer.File[];
    },
  ) {
    try {
      const result = await firstValueFrom(
        this.client.send({ cmd: 'customer_update' }, { id, body, files }),
      );

      return result;
    } catch (err) {
      console.log(err);
      throw new InternalServerErrorException('Something went wrong!');
    }
  }

  @Post('/verify-document-by-name/:id/:name')
  async verifyDocumentByName(
    @Param('id', ParseIntPipe) id: number,
    @Param('name') name: string,
    @Body() body: any,
  ) {
    try {
      console.log('gateway calling!');
      const result = await firstValueFrom(
        this.client.send(
          { cmd: 'verify_document_by_name' },
          { id, name, body },
        ),
      );

      return result;
    } catch (err) {
      const errorResponse = err;

      if (typeof errorResponse == 'object' && errorResponse.statusCode) {
        throw new HttpException(
          errorResponse.message,
          errorResponse.statusCode,
        );
      }

      throw new InternalServerErrorException(
        'Something went wrong when verifying the document2!',
      );
    }
  }
}
