import express, { Request, Response } from 'express';

import multer from 'multer';

import path from 'path';

import fs from 'fs/promises';

import { checkSnapshotThrottle } from '../utils/snapshotThrottle';

import { requirePhpAuth } from '../middleware/phpJwtAuth';



/**

 * อัปโหลดไฟล์สำหรับแชท — ไม่จำกัดประเภทไฟล์ แต่กันขนาดเกินด้วย MAX_FILE_SIZE

 * เก็บใน <project>/uploads/chat/<YYYY-MM>/<random>.<ext>

 * เปิดอ่าน/ดาวน์โหลดผ่าน static path /uploads/chat/...

 */



const router = express.Router();



const UPLOAD_ROOT = path.resolve(process.cwd(), 'uploads', 'chat');

const MAX_FILE_SIZE = Number(process.env.CHAT_UPLOAD_MAX_BYTES || 25 * 1024 * 1024); // default 25MB



function ensureDirAsync(dir: string, cb: (err: Error | null, dir: string) => void): void {

  fs.mkdir(dir, { recursive: true })

    .then(() => cb(null, dir))

    .catch((err) => cb(err, dir));

}



const storage = multer.diskStorage({

  destination: (_req, _file, cb) => {

    const month = new Date().toISOString().slice(0, 7); // YYYY-MM

    const dest = path.join(UPLOAD_ROOT, month);

    ensureDirAsync(dest, cb);

  },

  filename: (_req, file, cb) => {

    const ext = path.extname(file.originalname).toLowerCase().slice(0, 16);

    const safeBase = path.basename(file.originalname, path.extname(file.originalname))

      .replace(/[^\p{L}\p{N}_-]+/gu, '_')

      .slice(0, 60);

    const random = Math.random().toString(36).slice(2, 10);

    const ts = Date.now();

    cb(null, `${ts}_${random}_${safeBase}${ext}`);

  },

});



const upload = multer({

  storage,

  limits: { fileSize: MAX_FILE_SIZE },

});



router.post('/file', upload.single('file'), (req: Request, res: Response) => {

  try {

    if (!req.file) {

      return res.status(400).json({ success: false, message: 'No file uploaded' });

    }

    const month = path.basename(path.dirname(req.file.path));

    const fileName = path.basename(req.file.path);

    const publicPath = `/uploads/chat/${month}/${fileName}`;

    return res.json({

      success: true,

      data: {

        url: publicPath,

        filename: req.file.originalname,

        size: req.file.size,

        mime_type: req.file.mimetype,

      },

    });

  } catch (error: any) {

    console.error('❌ Upload error:', error);

    return res.status(500).json({ success: false, message: error?.message || 'Upload failed' });

  }

});



/* ========================================================

 * Exam snapshot upload (รูปจากกล้องนักเรียนขณะทำข้อสอบ)

 * memory → throttle ก่อนเขียน disk + ต้องมี JWT

 * ======================================================== */

const SNAPSHOT_ROOT = path.resolve(process.cwd(), 'uploads', 'exam-snapshots');

const MAX_SNAPSHOT_SIZE = Number(process.env.EXAM_SNAPSHOT_MAX_BYTES || 5 * 1024 * 1024); // 5MB



const snapshotMemoryUpload = multer({

  storage: multer.memoryStorage(),

  limits: { fileSize: MAX_SNAPSHOT_SIZE },

  fileFilter: (_req, file, cb) => {

    if (!/^image\//i.test(file.mimetype)) {

      return cb(new Error('Only image files allowed for exam snapshots'));

    }

    cb(null, true);

  },

});



router.post(

  '/exam-snapshot',

  requirePhpAuth,

  snapshotMemoryUpload.single('file'),

  async (req: Request, res: Response) => {

    try {

      const userId = String(req.authUser?.user_id || '').trim();

      if (!userId) {

        return res.status(401).json({ success: false, message: 'Unauthorized' });

      }



      const throttle = checkSnapshotThrottle(userId);

      if (!throttle.allowed) {

        return res.status(200).json({

          success: true,

          data: {

            throttled: true,

            retryAfterMs: throttle.retryAfterMs,

            message: 'Snapshot rate limited',

          },

        });

      }



      if (!req.file?.buffer?.length) {

        return res.status(400).json({ success: false, message: 'No snapshot uploaded' });

      }



      const courseId = String(req.body?.courseId || '');

      const recId = String(req.body?.recId || '');

      const itemId = String(req.body?.itemId || '');



      const day = new Date().toISOString().slice(0, 10);

      const safeUserDir = userId.replace(/[^A-Za-z0-9_-]/g, '_').slice(0, 40);

      const dest = path.join(SNAPSHOT_ROOT, day, safeUserDir);

      await fs.mkdir(dest, { recursive: true });



      const ext = path.extname(req.file.originalname).toLowerCase() || '.jpg';

      const fileName = `${Date.now()}_${Math.random().toString(36).slice(2, 8)}${ext}`;

      const filePath = path.join(dest, fileName);

      await fs.writeFile(filePath, req.file.buffer);



      const publicPath = `/uploads/exam-snapshots/${day}/${safeUserDir}/${fileName}`;



      const payload = {

        url: publicPath,

        size: req.file.size,

        mime_type: req.file.mimetype,

        userId,

        courseId,

        recId,

        itemId,

        capturedAt: new Date().toISOString(),

      };



      try {

        const io = req.app.locals.io;

        if (io) {

          io.to('exam:monitoring').emit('exam:snapshot:new', payload);

        }

      } catch (e) {

        console.warn('emit exam:snapshot:new failed', e);

      }



      return res.json({ success: true, data: payload });

    } catch (error: any) {

      console.error('❌ Exam snapshot upload error:', error);

      return res.status(500).json({ success: false, message: error?.message || 'Upload failed' });

    }

  },

);



router.use((err: any, _req: Request, res: Response, next: Function) => {

  if (err instanceof multer.MulterError) {

    res.status(400).json({ success: false, message: err.message });

    return;

  }

  if (err) {

    res.status(500).json({ success: false, message: err.message || 'Upload error' });

    return;

  }

  next();

});



export default router;


