import { Injectable, BadRequestException } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
import * as multer from 'multer';
import * as path from 'path';
import * as fs from 'fs';
import { v4 as uuidv4 } from 'uuid';

export interface UploadConfig {
  destination: string;
  allowedMimeTypes: string[];
  maxFileSize: number;
  filename?: (req: any, file: Express.Multer.File, cb: any) => void;
}

@Injectable()
export class UploadService {
  private readonly uploadsDir = 'uploads';

  constructor(private configService: ConfigService) {
    this.ensureUploadDirectories();
  }

  private ensureUploadDirectories(): void {
    const directories = [
      'profile-pictures',
      'cms',
      'products',
      'orders',
      'reports',
      'quality-control',
      'maintenance'
    ];

    directories.forEach(dir => {
      const fullPath = path.join(this.uploadsDir, dir);
      if (!fs.existsSync(fullPath)) {
        fs.mkdirSync(fullPath, { recursive: true });
      }
    });
  }

  getUploadConfig(type: string): UploadConfig {
    const configs: Record<string, UploadConfig> = {
      'profile-picture': {
        destination: path.join(this.uploadsDir, 'profile-pictures'),
        allowedMimeTypes: ['image/jpeg', 'image/png', 'image/gif', 'image/webp'],
        maxFileSize: 5 * 1024 * 1024, // 5MB
        filename: (req, file, cb) => {
          const uniqueName = `${uuidv4()}${path.extname(file.originalname)}`;
          cb(null, uniqueName);
        }
      },
      'cms': {
        destination: path.join(this.uploadsDir, 'cms'),
        allowedMimeTypes: ['image/jpeg', 'image/png', 'image/gif', 'image/webp', 'image/svg+xml'],
        maxFileSize: 10 * 1024 * 1024, // 10MB
        filename: (req, file, cb) => {
          const uniqueName = `${uuidv4()}${path.extname(file.originalname)}`;
          cb(null, uniqueName);
        }
      },
      'product': {
        destination: path.join(this.uploadsDir, 'products'),
        allowedMimeTypes: ['image/jpeg', 'image/png', 'image/gif', 'image/webp'],
        maxFileSize: 10 * 1024 * 1024, // 10MB
        filename: (req, file, cb) => {
          const uniqueName = `${uuidv4()}${path.extname(file.originalname)}`;
          cb(null, uniqueName);
        }
      },
      'order': {
        destination: path.join(this.uploadsDir, 'orders'),
        allowedMimeTypes: ['image/jpeg', 'image/png', 'application/pdf', 'text/plain'],
        maxFileSize: 20 * 1024 * 1024, // 20MB
        filename: (req, file, cb) => {
          const uniqueName = `${uuidv4()}${path.extname(file.originalname)}`;
          cb(null, uniqueName);
        }
      },
      'report': {
        destination: path.join(this.uploadsDir, 'reports'),
        allowedMimeTypes: ['application/pdf', 'application/msword', 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', 'text/plain'],
        maxFileSize: 50 * 1024 * 1024, // 50MB
        filename: (req, file, cb) => {
          const uniqueName = `${uuidv4()}${path.extname(file.originalname)}`;
          cb(null, uniqueName);
        }
      },
      'quality-control': {
        destination: path.join(this.uploadsDir, 'quality-control'),
        allowedMimeTypes: ['image/jpeg', 'image/png', 'image/gif', 'image/webp', 'application/pdf'],
        maxFileSize: 15 * 1024 * 1024, // 15MB
        filename: (req, file, cb) => {
          const uniqueName = `${uuidv4()}${path.extname(file.originalname)}`;
          cb(null, uniqueName);
        }
      },
      'maintenance': {
        destination: path.join(this.uploadsDir, 'maintenance'),
        allowedMimeTypes: ['image/jpeg', 'image/png', 'image/gif', 'image/webp', 'application/pdf', 'video/mp4', 'video/avi'],
        maxFileSize: 100 * 1024 * 1024, // 100MB
        filename: (req, file, cb) => {
          const uniqueName = `${uuidv4()}${path.extname(file.originalname)}`;
          cb(null, uniqueName);
        }
      }
    };

    const config = configs[type];
    if (!config) {
      throw new BadRequestException(`Invalid upload type: ${type}`);
    }

    return config;
  }

  createMulterConfig(type: string): multer.Options {
    const config = this.getUploadConfig(type);

    return {
      storage: multer.diskStorage({
        destination: (req, file, cb) => {
          cb(null, config.destination);
        },
        filename: config.filename || ((req, file, cb) => {
          const uniqueName = `${uuidv4()}${path.extname(file.originalname)}`;
          cb(null, uniqueName);
        })
      }),
      fileFilter: (req, file, cb) => {
        if (config.allowedMimeTypes.includes(file.mimetype)) {
          cb(null, true);
        } else {
          cb(null, false);
        }
      },
      limits: {
        fileSize: config.maxFileSize
      }
    };
  }

  async deleteFile(filePath: string): Promise<void> {
    try {
      if (fs.existsSync(filePath)) {
        fs.unlinkSync(filePath);
      }
    } catch (error) {
      console.error('Error deleting file:', error);
    }
  }

  getFileUrl(filename: string, type: string): string {
    return `/uploads/${type}/${filename}`;
  }

  getFilePath(filename: string, type: string): string {
    return path.join(this.uploadsDir, type, filename);
  }

  async saveBase64Image(base64Data: string, type: string, originalName?: string): Promise<string> {
    const config = this.getUploadConfig(type);
    const buffer = Buffer.from(base64Data.replace(/^data:image\/\w+;base64,/, ''), 'base64');
    const filename = `${uuidv4()}.${originalName ? path.extname(originalName) : 'png'}`;
    const filePath = path.join(config.destination, filename);

    fs.writeFileSync(filePath, buffer);
    return filename;
  }
} 