require('dotenv').config();
const express = require('express');
const http = require('http');
const path = require('path');
const fs = require('fs');
const multer = require('multer');
const { Server } = require('socket.io');

const {
  createRoom,
  getRoom,
  getOpenRooms,
  touchActivity,
  setRoomStatus,
  setRoomBlocked,
  addMessage,
  getMessages,
} = require('./db');
const { initBot } = require('./bot');

const UPLOAD_DIR = path.join(__dirname, 'public', 'uploads');
fs.mkdirSync(UPLOAD_DIR, { recursive: true });

// chat otomatis ditutup kalau gak ada aktivitas selama sekian menit (10-20 menit, default 15)
const AUTO_CLOSE_MINUTES = Number(process.env.AUTO_CLOSE_MINUTES) || 15;
const AUTO_CLOSE_MS = AUTO_CLOSE_MINUTES * 60 * 1000;

const storage = multer.diskStorage({
  destination: (req, file, cb) => cb(null, UPLOAD_DIR),
  filename: (req, file, cb) => {
    const unique = Date.now() + '-' + Math.round(Math.random() * 1e9);
    cb(null, unique + path.extname(file.originalname));
  },
});
const upload = multer({
  storage,
  limits: { fileSize: 25 * 1024 * 1024 }, // max 25MB (foto HP zaman sekarang bisa gede)
});

const PORT = process.env.PORT || 3000;
const BOT_TOKEN = process.env.BOT_TOKEN;
const ADMIN_CHAT_ID = process.env.ADMIN_CHAT_ID;

if (!BOT_TOKEN || !ADMIN_CHAT_ID) {
  console.error('❌ BOT_TOKEN atau ADMIN_CHAT_ID belum di-set di file .env');
  process.exit(1);
}

const app = express();

// izinkan widget dipanggil dari domain manapun (widget dipasang di website klien,
// beda domain dengan server ini) — tanpa ini semua request dari widget.js akan diblokir browser (CORS)
app.use((req, res, next) => {
  res.header('Access-Control-Allow-Origin', '*');
  res.header('Access-Control-Allow-Methods', 'GET, POST, OPTIONS');
  res.header('Access-Control-Allow-Headers', 'Content-Type');
  if (req.method === 'OPTIONS') return res.sendStatus(204);
  next();
});

app.use(express.json());
app.use(express.static(path.join(__dirname, 'public')));

const server = http.createServer(app);
const io = new Server(server, { cors: { origin: '*' } });

const { notifyNewChat, notifyNewMessage, notifyNewFile, notifyRoomClosed } = initBot({
  token: BOT_TOKEN,
  adminChatId: ADMIN_CHAT_ID,
  io,
});

const GREETING_TEXT = 'Selamat datang di Live Chat kami! Ada yang bisa kami bantu, bosku? 😊';

// visitor buka widget -> buat room baru
app.post('/api/chat/start', async (req, res) => {
  const { user, email, site } = req.body;
  const room = createRoom({
    user: user || `Guest-${Math.random().toString(16).slice(2, 8)}`,
    email: email || '',
    site: site || req.headers.referer || 'Direct',
  });

  // pesan sapaan otomatis, biar langsung nongol di widget & histori
  addMessage({ room_id: room.id, from: 'admin', text: GREETING_TEXT, type: 'text' });

  await notifyNewChat(room);
  res.json({ room });
});

// visitor kirim pesan
app.post('/api/chat/message', async (req, res) => {
  const { room_id, text } = req.body;
  const room = getRoom(room_id);
  if (!room) return res.status(404).json({ error: 'Room tidak ditemukan' });

  if (room.blocked) {
    return res.status(403).json({ error: 'blocked', message: 'Chat kamu telah diblokir oleh admin.' });
  }

  // kalau chat sebelumnya auto-close karena nganggur, buka lagi begitu visitor kirim pesan baru
  if (room.status === 'closed') {
    setRoomStatus(room_id, 'open');
  }
  touchActivity(room_id);

  const msg = addMessage({ room_id, from: 'user', text });
  await notifyNewMessage(room, text);

  res.json({ message: msg });
});

// visitor kirim gambar/file
app.post('/api/chat/upload', (req, res, next) => {
  upload.single('file')(req, res, (err) => {
    if (err) {
      const message =
        err.code === 'LIMIT_FILE_SIZE'
          ? 'Ukuran file terlalu besar (maksimal 25MB).'
          : 'Gagal upload file.';
      return res.status(400).json({ error: 'upload_failed', message });
    }
    next();
  });
}, async (req, res) => {
  const { room_id, caption } = req.body;
  const room = getRoom(room_id);
  if (!room) return res.status(404).json({ error: 'Room tidak ditemukan' });
  if (!req.file) return res.status(400).json({ error: 'File tidak ditemukan' });

  if (room.blocked) {
    fs.unlink(req.file.path, () => {});
    return res.status(403).json({ error: 'blocked', message: 'Chat kamu telah diblokir oleh admin.' });
  }

  if (room.status === 'closed') {
    setRoomStatus(room_id, 'open');
  }
  touchActivity(room_id);

  const isImage = req.file.mimetype.startsWith('image/');
  const type = isImage ? 'image' : 'file';
  const url = '/uploads/' + req.file.filename;

  const msg = addMessage({
    room_id,
    from: 'user',
    text: caption || req.file.originalname,
    type,
    url,
    filename: req.file.originalname,
  });

  await notifyNewFile(room, {
    type,
    filePath: req.file.path,
    filename: req.file.originalname,
  });

  res.json({ message: msg });
});

// ambil histori chat (dipakai widget saat reload)
app.get('/api/chat/history/:room_id', (req, res) => {
  const room = getRoom(req.params.room_id);
  const messages = getMessages(req.params.room_id);
  res.json({
    messages,
    room: room ? { id: room.id, status: room.status, blocked: room.blocked } : null,
  });
});

// realtime: widget join room-nya sendiri biar bisa terima balasan admin
io.on('connection', (socket) => {
  socket.on('join_room', (room_id) => {
    socket.join(`room_${room_id}`);
  });
});

// cek berkala: tutup otomatis chat yang nganggur lebih dari AUTO_CLOSE_MINUTES
setInterval(() => {
  const now = Date.now();
  const openRooms = getOpenRooms();

  openRooms.forEach((room) => {
    if (room.blocked) return; // room yang diblokir gak usah diotak-atik status auto-close
    const lastActivity = new Date(room.last_activity || room.created_at).getTime();
    if (now - lastActivity >= AUTO_CLOSE_MS) {
      setRoomStatus(room.id, 'closed');
      io.to(`room_${room.id}`).emit('room_closed', {
        room_id: room.id,
        reason: 'inactivity',
        ts: new Date().toISOString(),
      });
      notifyRoomClosed(room, AUTO_CLOSE_MINUTES).catch(() => {});
    }
  });
}, 60 * 1000); // cek tiap 1 menit

server.listen(PORT, () => {
  console.log(`✅ Livechat server jalan di http://localhost:${PORT}`);
});