require('dotenv').config();
const express = require('express');
const expressLayouts = require('express-ejs-layouts');
const session = require('express-session');
const PgSession = require('connect-pg-simple')(session);
const passport = require('passport');
const DiscordStrategy = require('passport-discord').Strategy;
const { Client, GatewayIntentBits, Partials, REST, Routes } = require('discord.js');
const csrf = require('csurf');
const cors = require('cors');
const path = require('path');
const { Pool } = require('pg');

const authRoutes = require('./routes/auth');
const adminRoutes = require('./routes/admin/index');
const webhookRoutes = require('./routes/webhook');
const stripeRoutes = require('./routes/stripe');
const apiRoutes = require('./routes/api');
const mvcRoutes = require('./routes/mvc');
const { registerEvents } = require('./discord/events');
const { linkCommand } = require('./discord/commands');
const { createServerCommand } = require('./discord/createserver');
const { delServerCommand } = require('./discord/delserver');
const { tasksCommand } = require('./discord/tasks');
const { verifyMvcCommand } = require('./discord/verifymvc');
const { initCron } = require('./sync/cron');
const discordRoleSync = require('./services/discordRoleSync');

// PostgreSQL connection pool for sessions
const pgPool = new Pool({
    user: process.env.DB_USER,
    host: process.env.DB_HOST,
    database: process.env.DB_NAME,
    password: process.env.DB_PASSWORD,
    port: process.env.DB_PORT || 5432
});

// Initialize Discord Client
const client = new Client({
    intents: [
        GatewayIntentBits.Guilds,
        GatewayIntentBits.GuildMembers,
        GatewayIntentBits.GuildMessageReactions,
        GatewayIntentBits.DirectMessages
    ],
    // Partials needed so reaction events fire for messages not in cache (bot-owned
    // #get-roles messages are from before current session).
    partials: [Partials.Message, Partials.Channel, Partials.Reaction]
});
registerEvents(client);

// Passport Configuration
passport.serializeUser((user, done) => done(null, user));
passport.deserializeUser((obj, done) => done(null, obj));

passport.use(new DiscordStrategy({
    clientID: process.env.DISCORD_CLIENT_ID,
    clientSecret: process.env.DISCORD_CLIENT_SECRET,
    callbackURL: process.env.REDIRECT_URI,
    scope: ['identify']
}, (accessToken, refreshToken, profile, done) => {
    return done(null, profile);
}));

// Initialize Express App
const app = express();
app.set('trust proxy', 1);
app.set('view engine', 'ejs');
app.set('views', __dirname + '/views');

// Enable proper layout rendering with express-ejs-layouts
app.use(expressLayouts);
app.set('layout', 'layout'); // Default layout is views/layout.ejs

// HTMX Middleware: Disable layout wrapper for HTMX AJAX requests
// HTMX sends HX-Request header - these requests need raw HTML fragments, not full layout
app.use((req, res, next) => {
  if (req.headers['hx-request']) {
    res.locals.layout = false;
  }
  next();
});

// CRITICAL: Stripe webhook needs raw body BEFORE express.json() middleware
// Mounted at /webhooks/stripe to avoid conflict with /stripe checkout mount
app.use('/webhooks/stripe', stripeRoutes);

// Static files (PWA manifest, icons, service worker)
app.use(express.static(path.join(__dirname, 'public')));

// Body parsing middleware (comes AFTER webhook route)
app.use(express.json());
app.use(express.urlencoded({ extended: true }));

// Make Discord client accessible to routes
app.locals.client = client;

app.use(session({
    store: new PgSession({
        pool: pgPool,
        tableName: 'session',
        createTableIfMissing: true
    }),
    secret: process.env.SESSION_SECRET,
    resave: false,
    saveUninitialized: false,
    cookie: {
      secure: process.env.NODE_ENV === 'production',
      maxAge: 7 * 24 * 60 * 60 * 1000
    }
}));
app.use(passport.initialize());
app.use(passport.session());

// Health Check
app.get('/health', (req, res) => {
    res.json({ 
      status: 'online', 
      uptime: process.uptime(), 
      bot: client.user?.tag || 'not ready'
    });
});

// Root redirect to admin
app.get('/', (req, res) => res.redirect('/admin'));

// CSRF Protection (session-based)
const csrfProtection = csrf({ cookie: false });

// Register Routes
app.use('/auth', authRoutes);
app.use('/admin', csrfProtection, adminRoutes);
app.use('/webhook', webhookRoutes);
app.use('/stripe', stripeRoutes); // Checkout and portal routes (uses JSON body)
app.use('/api/internal', apiRoutes); // Internal API for n8n (token-based auth)
app.use('/api/mvc', mvcRoutes);     // ModpackChecker licensing API (public)

// Start Application
const PORT = process.env.PORT || 3500;
app.listen(PORT, () => {
    console.log(`🌐 Express server running on port ${PORT}`);
    console.log(`📍 Admin panel: https://discord-bot.firefrostgaming.com/admin`);
    client.login(process.env.DISCORD_BOT_TOKEN);
});

// Register Slash Commands
const rest = new REST({ version: '10' }).setToken(process.env.DISCORD_BOT_TOKEN);
(async () => {
  try {
    console.log('Refreshing application (/) commands.');
    await rest.put(
      Routes.applicationGuildCommands(process.env.DISCORD_CLIENT_ID, process.env.GUILD_ID),
      { body: [linkCommand.toJSON(), createServerCommand.toJSON(), delServerCommand.toJSON(), tasksCommand.toJSON(), verifyMvcCommand.toJSON()] },
    );
    console.log('✅ Successfully reloaded application (/) commands.');
  } catch (error) {
    console.error('Failed to register slash commands:', error);
  }
})();

// Initialize pg-boss job queue (Task #101 — Modpack Installer)
const PgBoss = require('pg-boss');
const { handleInstallJob } = require('./services/modpackInstaller');
(async () => {
  try {
    const boss = new PgBoss({
      host: process.env.DB_HOST,
      database: process.env.DB_NAME,
      user: process.env.DB_USER,
      password: process.env.DB_PASSWORD,
      port: process.env.DB_PORT || 5432
    });
    await boss.start();
    await boss.work('modpack-installs', { teamConcurrency: 2 }, handleInstallJob);
    app.locals.pgBoss = boss;
    console.log('✅ pg-boss job queue initialized (modpack-installs concurrency: 2)');
  } catch (err) {
    console.error('⚠️ pg-boss init failed (installer will not work):', err.message);
  }
})();

// Initialize Hourly Cron Job
initCron();
console.log('✅ Hourly sync cron initialized.');

// Initialize Server Status Poller (updates Discord status channels every 5 minutes)
const serverStatusPoller = require('./services/serverStatusPoller');
serverStatusPoller.start(5); // 5 minute interval
console.log('✅ Server status poller initialized (5 min interval).');

// Error handling
process.on('unhandledRejection', error => {
  console.error('❌ Unhandled promise rejection:', error);
});
