import { InjectQueue, Process, Processor } from '@nestjs/bull';
import { InjectRepository } from '@nestjs/typeorm';
import { Job, Queue } from 'bull';
import { Repository } from 'typeorm';
import { AssetEntity } from '../../api-v1/asset/entities/asset.entity';
import sharp from 'sharp';
import { existsSync, mkdirSync, readFile } from 'fs';
import { ConfigService } from '@nestjs/config';
import ffmpeg from 'fluent-ffmpeg';
import { APP_UPLOAD_LOCATION } from '../../constants/upload_location.constant';
import { WebSocketServer } from '@nestjs/websockets';
import { Socket, Server as SocketIoServer } from 'socket.io';
import { CommunicationGateway } from '../../api-v1/communication/communication.gateway';
import { BackgroundTaskService } from '../background-task/background-task.service';

@Processor('optimize')
export class ImageOptimizeProcessor {
  constructor(
    private wsCommunicateionGateway: CommunicationGateway,
    @InjectRepository(AssetEntity)
    private assetRepository: Repository<AssetEntity>,

    private backgroundTaskService: BackgroundTaskService,
  ) {}

  @Process('resize-image')
  async resizeUploadedImage(job: Job) {
    const { savedAsset }: { savedAsset: AssetEntity } = job.data;

    const basePath = APP_UPLOAD_LOCATION;
    const resizePath = savedAsset.originalPath.replace('/original/', '/thumb/');

    // Create folder for thumb image if not exist

    const resizeDir = `${basePath}/${savedAsset.userId}/thumb/${savedAsset.deviceId}`;

    if (!existsSync(resizeDir)) {
      mkdirSync(resizeDir, { recursive: true });
    }

    readFile(savedAsset.originalPath, async (err, data) => {
      if (err) {
        console.error('Error Reading File');
      }

      if (savedAsset.mimeType == 'image/heic' || savedAsset.mimeType == 'image/heif') {
        let desitnation = '';
        if (savedAsset.mimeType == 'image/heic') {
          desitnation = resizePath.replace('.HEIC', '.jpeg');
        } else {
          desitnation = resizePath.replace('.HEIF', '.jpeg');
        }

        sharp(data)
          .toFormat('jpeg')
          .resize(512, 512, { fit: 'outside' })
          .toFile(desitnation, async (err, info) => {
            if (err) {
              console.error('Error resizing file ', err);
              return;
            }

            const res = await this.assetRepository.update(savedAsset, { resizePath: desitnation });

            if (res.affected) {
              this.wsCommunicateionGateway.server
                .to(savedAsset.userId)
                .emit('on_upload_success', JSON.stringify(savedAsset));
            }

            // Tag Image
            this.backgroundTaskService.tagImage(desitnation, savedAsset);
          });
      } else {
        sharp(data)
          .resize(512, 512, { fit: 'outside' })
          .toFile(resizePath, async (err, info) => {
            if (err) {
              console.error('Error resizing file ', err);
              return;
            }

            const res = await this.assetRepository.update(savedAsset, { resizePath: resizePath });
            if (res.affected) {
              this.wsCommunicateionGateway.server
                .to(savedAsset.userId)
                .emit('on_upload_success', JSON.stringify(savedAsset));
            }

            // Tag Image
            this.backgroundTaskService.tagImage(resizePath, savedAsset);
          });
      }
    });

    return 'ok';
  }

  @Process('get-video-thumbnail')
  async resizeUploadedVideo(job: Job) {
    const { savedAsset, filename }: { savedAsset: AssetEntity; filename: String } = job.data;

    const basePath = APP_UPLOAD_LOCATION;
    // const resizePath = savedAsset.originalPath.replace('/original/', '/thumb/');
    // Create folder for thumb image if not exist
    const resizeDir = `${basePath}/${savedAsset.userId}/thumb/${savedAsset.deviceId}`;

    if (!existsSync(resizeDir)) {
      mkdirSync(resizeDir, { recursive: true });
    }

    ffmpeg(savedAsset.originalPath)
      .thumbnail({
        count: 1,
        timestamps: [1],
        folder: resizeDir,
        filename: `${filename}.png`,
      })
      .on('end', async (a) => {
        const thumbnailPath = `${resizeDir}/${filename}.png`;

        const res = await this.assetRepository.update(savedAsset, { resizePath: `${resizeDir}/${filename}.png` });

        if (res.affected) {
          this.wsCommunicateionGateway.server
            .to(savedAsset.userId)
            .emit('on_upload_success', JSON.stringify(savedAsset));
        }

        // Tag Image
        this.backgroundTaskService.tagImage(thumbnailPath, savedAsset);
      });

    return 'ok';
  }
}