const express     = require('express');
const cors        = require('cors');
const helmet      = require('helmet');
const path        = require('path');
const rateLimit   = require('express-rate-limit');
const { ensureBucket, client, BUCKET } = require('./config/minio');
const prisma      = require('./config/db');

const app  = express();
const PORT = process.env.PORT || 3201;

// ── 기본 미들웨어 ────────────────────────────────────────────────────────────
app.set('trust proxy', 1);
app.use(helmet({ crossOriginResourcePolicy: false }));
app.use(cors({
  origin: process.env.ALLOWED_ORIGIN || '*',
  credentials: true,
}));
app.use(express.json({ limit: '2mb' }));
app.use(express.urlencoded({ extended: true, limit: '2mb' }));

// ── Rate Limiting ────────────────────────────────────────────────────────────
const limiter = rateLimit({
  windowMs: 15 * 60 * 1000,
  max: 300,
  standardHeaders: true,
  legacyHeaders: false,
  message: { error: '요청이 너무 많습니다. 잠시 후 다시 시도해주세요.' },
});
const authLimiter = rateLimit({
  windowMs: 15 * 60 * 1000,
  max: 20,
  message: { error: '로그인 시도가 너무 많습니다.' },
});

app.use('/api/', limiter);
app.use('/api/auth/login',    authLimiter);
app.use('/api/auth/register', authLimiter);

// ── MinIO 파일 프록시 ─────────────────────────────────────────────────────────
// /api/files/images/xxx.webp → MinIO BUCKET/images/xxx.webp 스트리밍
// esp-web-tools가 bin 파일을 직접 fetch할 때 CORS 헤더 포함
const MIME = {
  '.webp': 'image/webp', '.jpg': 'image/jpeg', '.jpeg': 'image/jpeg',
  '.png': 'image/png', '.gif': 'image/gif', '.svg': 'image/svg+xml',
  '.bin': 'application/octet-stream', '.stl': 'model/stl',
  '.pdf': 'application/pdf', '.mp4': 'video/mp4', '.webm': 'video/webm',
};

app.get('/api/files/*', async (req, res) => {
  try {
    const objectName = req.params[0];
    if (!objectName) return res.status(400).end();

    const ext         = path.extname(objectName).toLowerCase();
    const contentType = MIME[ext] || 'application/octet-stream';

    res.setHeader('Content-Type', contentType);
    res.setHeader('Access-Control-Allow-Origin', '*');
    res.setHeader('Cache-Control', 'public, max-age=86400');

    const stream = await client.getObject(BUCKET, objectName);
    stream.pipe(res);
    stream.on('error', () => res.status(404).end());
  } catch {
    res.status(404).end();
  }
});

// ── 라우트 ───────────────────────────────────────────────────────────────────
app.use('/api/auth',     require('./routes/auth'));
app.use('/api/projects', require('./routes/projects'));
app.use('/api/products', require('./routes/products'));
app.use('/api/orders',   require('./routes/orders'));
app.use('/api/flash',    require('./routes/flash'));
app.use('/api/admin',    require('./routes/admin'));

// 헬스 체크
app.get('/api/health', (_req, res) => {
  res.json({ status: 'ok', timestamp: new Date().toISOString() });
});

// ── 오류 핸들러 ─────────────────────────────────────────────────────────────
app.use((err, _req, res, _next) => {
  console.error(err);
  res.status(err.status || 500).json({ error: err.message || '서버 오류' });
});

// ── 시작 ─────────────────────────────────────────────────────────────────────
async function start() {
  try {
    await prisma.$connect();
    console.log('PostgreSQL connected');

    await ensureBucket();
    console.log('MinIO ready');

    app.listen(PORT, () => {
      console.log(`Platform Backend → http://localhost:${PORT}`);
    });
  } catch (err) {
    console.error('Startup error:', err);
    process.exit(1);
  }
}

start();
