const express = require('express');
const bodyParser = require('body-parser');
const cors = require('cors');
const http = require('http');
const socketIo = require('socket.io');

const adminRoutes = require('./routes/adminRoutes');
const authRoutes = require('./routes/authRoutes');
const eventRoutes = require('./routes/eventRoutes');
const publicEventRoutes = require('./routes/publicEventRoutes');
const clubRoutes = require('./routes/clubRoutes');
const userRoutes = require('./routes/userRoutes');
const notificationRoutes = require('./routes/notificationRoutes');
const menuRoutes = require('./routes/menuRoutes');
const subscriptionRoutes = require('./routes/subscriptionRoutes');
const featureRoutes = require('./routes/featureRoutes');
const { sequelize, syncModels } = require('./models');

const app = express();
const server = http.createServer(app);
const io = socketIo(server, {
  cors: {
    origin: '*',
    methods: ['GET', 'POST']
  }
});

function getDomain(origin) {
  try {
    const url = new URL(origin);
    return url.hostname; // 'lanebow.com', 'localhost'
  } catch (e) {
    return null;
  }
}

const allowedDomains = ['lanebow.com', 'www.lanebow.com', 'localhost'];

app.use(cors({
  origin: function(origin, callback) {
    if (!origin) return callback(null, true);
    const domain = getDomain(origin);
    if (allowedDomains.includes(domain)) {
      return callback(null, true);
    } else {
      return callback(new Error('Not allowed by CORS'), false);
    }
  },
  credentials: true
}));
app.use(bodyParser.json());

// Socket.IO 연결 처리
io.on('connection', (socket) => {
  console.log('새로운 클라이언트 연결:', socket.id);
  
  // 사용자 인증 및 알림 룸 참여
  socket.on('authenticate', (userData) => {
    if (userData && userData.id) {
      socket.join(`user:${userData.id}`);
      console.log(`사용자 ${userData.id}가 알림 룸에 참여했습니다.`);
    }
  });
  
  // 연결 해제 처리
  socket.on('disconnect', () => {
    console.log('클라이언트 연결 해제:', socket.id);
  });
});

// 전역 Socket.IO 인스턴스 설정
app.set('io', io);
app.set('trust proxy', 1);
// 치명적 예외/비동기 에러 글로벌 로그
process.on('uncaughtException', (err) => {
  console.error('[FATAL] Uncaught Exception:', err);
});
process.on('unhandledRejection', (reason, promise) => {
  console.error('[FATAL] Unhandled Rejection:', reason);
});

// app.js 또는 서버 초기화 파일
const session = require('express-session');
const MySQLStore = require('express-mysql-session')(session);

// MySQL 세션 저장소 옵션 설정
const options = {
  host: process.env.DB_HOST || 'localhost',
  port: process.env.DB_PORT || 3306,
  user: process.env.DB_USER || 'root',
  password: process.env.DB_PASSWORD || '',
  database: process.env.DB_NAME || 'bowlingmanager',
  // 세션 테이블 설정
  schema: {
    tableName: 'sessions',
    columnNames: {
      session_id: 'session_id',
      expires: 'expires',
      data: 'data'
    }
  }
};

// MySQL 세션 저장소 생성
const sessionStore = new MySQLStore(options);

const baseSessionOptions = {
  key: 'bowling_session',
  secret: process.env.JWT_SECRET,
  store: sessionStore,
  resave: false,
  saveUninitialized: false,
  cookie: {
    maxAge: 24 * 60 * 60 * 1000,
    secure: false,
    sameSite: 'lax'
  }
};
app.use(session(baseSessionOptions));

// 요청마다 secure/sameSite를 동적으로 할당
app.use((req, res, next) => {
  const origin = req.headers.origin;
  const domain = getDomain(origin);
  if (req.session && req.session.cookie) {
    if (domain === 'lanebow.com') {
      req.session.cookie.secure = true;
      req.session.cookie.sameSite = 'none';
    } else {
      req.session.cookie.secure = false;
      req.session.cookie.sameSite = 'lax';
    }
  }
  next();
});

// 데이터베이스 연결 및 모델 동기화 실행
sequelize.authenticate()
  .then(() => {
    console.log('데이터베이스에 연결되었습니다.');
    return syncModels();
  })
  .then(() => {
    console.log('데이터베이스 모델이 동기화되었습니다.');
  })
  .catch(err => {
    console.error('데이터베이스 연결 또는 모델 동기화 오류:', err);
  });

// Routes 설정
app.use('/api/auth', authRoutes);
app.use('/api/admin', adminRoutes);  
app.use('/api/club', clubRoutes);
app.use('/api/club/events', eventRoutes);
app.use('/api/public', publicEventRoutes);
app.use('/api/features', featureRoutes);
app.use('/api/subscriptions', subscriptionRoutes);
app.use('/api/users', userRoutes);
app.use('/api/notifications', notificationRoutes);
app.use('/api/menus', menuRoutes);

// 정적 파일 제공 설정 (Flutter Web 빌드 산출물: mobile/build/web)
const path = require('path');
const WEB_ROOT = process.env.FRONTEND_ROOT || path.join(__dirname, '../mobile/build/web');
app.use(express.static(WEB_ROOT));

// API 요청이 아닌 모든 요청은 Flutter Web 앱으로 라우팅 (SPA Fallback)
app.get('*', (req, res, next) => {
  if (req.path.startsWith('/api/')) {
    return next();
  }
  res.sendFile(path.join(WEB_ROOT, 'index.html'));
});

// 서버 시작
const PORT = process.env.PORT || 3030;
server.listen(PORT, () => {
  console.log(`서버가 ${process.env.NODE_ENV} 환경으로 포트 ${PORT}에서 실행 중입니다.`);
});

module.exports = app;
