const express = require('express');
const path = require('node:path');
const multer = require('multer');
const {
  createContractPdf,
  listTemplates,
  getTemplatePreviewPdf,
  saveTemplate,
  deleteTemplate,
  getTemplateDefaults,
  saveTemplateDefaults,
} = require('./src/contractService');

const app = express();
const port = Number(process.env.PORT || 3001);
const ADMIN_PASSWORD = process.env.ADMIN_PASSWORD || 'admin';

if (!process.env.ADMIN_PASSWORD) {
  console.warn('[warn] ADMIN_PASSWORD 未設定，使用預設密碼 "admin"');
}

app.use(express.json({ limit: '1mb' }));
app.use(express.static(path.join(__dirname, 'public')));

function adminAuth(req, res, next) {
  const auth = req.headers.authorization || '';
  if (!auth.startsWith('Basic ')) {
    return res.status(401).json({ error: '需要管理員驗證。' });
  }
  const decoded = Buffer.from(auth.slice(6), 'base64').toString('utf-8');
  const password = decoded.slice(decoded.indexOf(':') + 1);
  if (password !== ADMIN_PASSWORD) {
    return res.status(401).json({ error: '密碼錯誤。' });
  }
  next();
}

const upload = multer({
  storage: multer.memoryStorage(),
  fileFilter: (_req, file, cb) => {
    const name = Buffer.from(file.originalname, 'latin1').toString('utf8');
    file.originalname = name;
    const ext = path.extname(name).toLowerCase();
    if (ext === '.doc' || ext === '.docx') return cb(null, true);
    const err = new Error('僅接受 .doc / .docx 檔案。');
    err.exposeToClient = true;
    cb(err);
  },
  limits: { fileSize: 10 * 1024 * 1024 },
});

// ── Public routes ──────────────────────────────────────────

app.get('/api/health', (_req, res) => {
  res.json({ ok: true });
});

app.get('/api/templates', async (_req, res, next) => {
  try {
    res.json({ templates: await listTemplates() });
  } catch (error) {
    next(error);
  }
});

app.get('/api/templates/:name/defaults', async (req, res, next) => {
  try {
    res.json(await getTemplateDefaults(req.params.name));
  } catch (error) {
    next(error);
  }
});

app.get('/api/templates/:name/preview', async (req, res) => {
  try {
    const pdfBuffer = await getTemplatePreviewPdf(req.params.name, req.query);
    res.setHeader('Content-Type', 'application/pdf');
    res.setHeader('Cache-Control', 'no-store');
    res.send(pdfBuffer);
  } catch (error) {
    console.error(error);
    const msg = error.exposeToClient ? error.message : '預覽失敗';
    res.status(error.exposeToClient ? 400 : 500)
      .send(`<!DOCTYPE html><html><body style="padding:20px;color:#666;font-family:sans-serif">${msg}</body></html>`);
  }
});

app.post('/api/contracts/pdf', async (req, res) => {
  try {
    const result = await createContractPdf({
      template: req.body.template,
      monthlyRent: req.body.monthlyRent,
      paymentDay: req.body.paymentDay,
      deposit: req.body.deposit,
      cleaningFee: req.body.cleaningFee,
      leaseStart: req.body.leaseStart,
      leaseEnd: req.body.leaseEnd,
    });

    await saveTemplateDefaults(req.body.template, {
      monthlyRent: req.body.monthlyRent,
      paymentDay: req.body.paymentDay,
      deposit: req.body.deposit,
      cleaningFee: req.body.cleaningFee,
    }).catch(() => {});

    res.setHeader('Content-Type', 'application/pdf');
    res.setHeader(
      'Content-Disposition',
      `attachment; filename="rental-contract.pdf"; filename*=UTF-8''${encodeURIComponent(result.fileName)}`,
    );
    res.setHeader('Cache-Control', 'no-store');
    res.send(result.buffer);
  } catch (error) {
    console.error(error);
    const status = error.exposeToClient ? 400 : 500;
    res.status(status).json({
      error: error.exposeToClient
        ? error.message
        : 'PDF 產生失敗，請確認 LibreOffice 已安裝且範本格式正確。',
    });
  }
});

// ── Admin routes ───────────────────────────────────────────

app.get('/api/admin/check', adminAuth, (_req, res) => {
  res.json({ ok: true });
});

app.post('/api/admin/templates', adminAuth, (req, res) => {
  upload.single('template')(req, res, async (err) => {
    if (err) {
      const status = err.exposeToClient || err instanceof multer.MulterError ? 400 : 500;
      return res.status(status).json({ error: err.message });
    }
    try {
      if (!req.file) return res.status(400).json({ error: '請選擇檔案。' });
      const name = await saveTemplate(req.file.originalname, req.file.buffer);
      res.json({ ok: true, name });
    } catch (error) {
      console.error(error);
      res.status(error.exposeToClient ? 400 : 500).json({
        error: error.exposeToClient ? error.message : '上傳失敗。',
      });
    }
  });
});

app.delete('/api/admin/templates/:name', adminAuth, async (req, res, next) => {
  try {
    await deleteTemplate(req.params.name);
    res.json({ ok: true });
  } catch (error) {
    next(error);
  }
});

// ── Error handler ──────────────────────────────────────────

app.use((error, _req, res, _next) => {
  console.error(error);
  const status = error.exposeToClient ? 400 : 500;
  res.status(status).json({
    error: error.exposeToClient ? error.message : '伺服器發生錯誤。',
  });
});

app.listen(port, () => {
  console.log(`Rental contract PDF app is running at http://localhost:${port}`);
});
