import express from 'express';
import cors from 'cors';
import helmet from 'helmet';
import morgan from 'morgan';
import 'express-async-errors';
import { Server } from 'socket.io';
import cookieParser from 'cookie-parser';

import tweetsRouter from './router/tweets.js';
import authRouter from './router/auth.js';
import { config } from './config.js';
import { connectDB } from './db/mongo.js';
import { msDB } from './db/mysql.js';
import { csrfCheck } from './middleware/csrf.js';
import rateLimit from './middleware/rate-limiter.js';

const app = express();
const corsOption = {
  origin: config.cors.allowedOrigin,
  optionsSuccessStatus: 200,
  credentials: true, // allow the Access-Control-Allow-Credentials
  // -> 서버에서 하는 대부분의 설정들은 반응 헤더를 설정한다고 봐도 무방할 것 같아요.
  // -> 서버에서 response를 보낼 때, 꼭 credentials: true로 설정해야 반응 헤더에 Access-Control-Allow-Credentials 이 포함되고,
  //    브라우저가 서버로 부터 데이터를 받았을 때 클라이언트의 JavaScript 로 body 안의 데이터를 보내줄 수 있기 때문이다.
};

// 기본 미들웨어 설정
// - 각 함수의 호출이나 지정으로 callback 함수를 반환한다.
app.use(express.json());   // 서버로 요청된 데이터 json으로 변경
app.use(cookieParser());   // cookie 적용
app.use(cors(corsOption)); // cors 적용
app.use(helmet());         // header 에 보안 속성 요소들 포함
app.use(morgan('tiny'));   // 로그 적용 및 레벨 설정
app.use(csrfCheck);        // csrf 보안 적용
app.use(rateLimit);        // 많은 요청 발생에 대한 요청횟수와 지연시간 적용

// Route(tweets)
app.use('/tweets', tweetsRouter);
// Route(Auth)
app.use('/auth', authRouter);

// 404 Error
app.use((req, res, next) => {
  res.sendStatus(404);
});

// Error
app.use((error, req, res, next) => {
  console.log(error);
  res.status(error.status || 500).json({
    message: error.message,
  });
});

// [ MySQL ]

// [ MongoDB ]
connectDB().then(() => {
  const server = app.listen(config.port);
  if (server) {
    console.log('server start !!!!');
  }
}).catch(console.error);

credentials

→ 클라이언트 단에서 클라이언트가 서버로 요청을 보낼때, ‘어떤 경우’ 에 쿠키 정보를 포함해서 보낼건지를 설정할 수 있다. 그래서 클라이언트에서 credentials 속성에 some-origin 이나 include 를 지정하면 자동으로 브라우저가 쿠키의 정보를 읽어서 header 에 포함되어 서버로 전달된다.

그렇기 때문에 서버에서 credentialstrue 값을 설정해 주어야 브라우저가 서버로 부터 데이터를 받았을 때 클라이언트의 JavaScript 로 body 안의 데이터를 보내줄 수 있기 때문이다.