require('dotenv').config();
const express = require('express');
const cors = require('cors');
const helmet = require('helmet');
const rateLimit = require('express-rate-limit');
const path = require('path');
const fs = require('fs');
const cookieParser = require('cookie-parser');
const logger = require('./utils/logger');

const authRoutes = require('./routes/auth.routes');
const userRoutes = require('./routes/user.routes');
const categoryRoutes = require('./routes/category.routes');
const productRoutes = require('./routes/product.routes');
const customerRoutes = require('./routes/customer.routes');
const transactionRoutes = require('./routes/transaction.routes');
const ticketRoutes = require('./routes/ticket.routes');
const dailyEntryRoutes = require('./routes/dailyEntry.routes');
const expenseEntryRoutes = require('./routes/expenseEntry.routes');
const airlineRoutes = require('./routes/airline.routes');
const reportRoutes = require('./routes/report.routes');
const auditLogRoutes = require('./routes/auditLog.routes');
const sessionRoutes = require('./routes/session.routes');
const settingsRoutes = require('./routes/settings.routes');
const timesheetRoutes = require('./routes/timesheet.routes');

const errorHandler = require('./middlewares/errorHandler');

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

// ── Global Middleware ──
app.use(helmet());

const allowedOrigins = [
  'http://localhost:3000',
  'http://127.0.0.1:3000',
  'https://nexus.sakiulhasansifat.my.id',
  'http://localhost',
  'http://192.168.0.100',
  'https://nexusnextgen.store',
  process.env.FRONTEND_URL,
  process.env.APP_URL,
  ...(process.env.CORS_ORIGINS || '').split(','),
]
  .map((origin) => origin && origin.trim())
  .filter(Boolean);

const isOriginAllowed = (origin) => !origin || allowedOrigins.includes(origin);
const corsOrigin = (origin, cb) => {
  // Allow requests with no origin (mobile apps, curl, same-origin)
  if (isOriginAllowed(origin)) return cb(null, true);
  return cb(new Error('Not allowed by CORS'));
};

app.use(cors({
  origin: corsOrigin,
  credentials: true,
}));
app.use(cookieParser());
app.use(express.json({ limit: '2mb' }));

// Rate limit auth endpoints (login, register, TOTP)
const authLimiter = rateLimit({
  windowMs: 15 * 60 * 1000, // 15 minutes
  max: 20,                   // 20 requests per window per IP
  standardHeaders: true,
  legacyHeaders: false,
  message: { error: 'Too many requests, please try again later.' },
});
app.use('/api/auth', authLimiter);

// ── Static file serving for uploads ──
// Serve uploads: prefer `src/uploads` (same level as this file),
// fall back to `../uploads` if not present.
const localUploads = path.join(__dirname, 'uploads');
const parentUploads = path.join(__dirname, '..', 'uploads');
const uploadsDir = fs.existsSync(localUploads) ? localUploads : parentUploads;

// Serve uploads both at /uploads and /api/uploads to support proxy prefixing
app.use([
  '/uploads',
  '/api/uploads',
],
  cors({ origin: corsOrigin }),
  express.static(uploadsDir, {
    setHeaders: (res) => {
      res.setHeader('Cross-Origin-Resource-Policy', 'cross-origin');
    },
  })
);

// Log uploads path for debugging
logger.info('Uploads served from:', uploadsDir);

// ── Health Check ──
app.get('/api/health', (_req, res) => {
  res.json({ status: 'ok', timestamp: new Date().toISOString() });
});

// ── Routes ──
app.use('/api/auth', authRoutes);
app.use('/api/users', userRoutes);
app.use('/api/categories', categoryRoutes);
app.use('/api/products', productRoutes);
app.use('/api/customers', customerRoutes);
app.use('/api/transactions', transactionRoutes);
app.use('/api/tickets', ticketRoutes);
app.use('/api/daily-entries', dailyEntryRoutes);
app.use('/api/expense-entries', expenseEntryRoutes);
app.use('/api/airlines', airlineRoutes);
app.use('/api/reports', reportRoutes);
app.use('/api/audit-logs', auditLogRoutes);
app.use('/api/sessions', sessionRoutes);
app.use('/api/settings', settingsRoutes);
app.use('/api/timesheet', timesheetRoutes);

// ── Error Handler ──
app.use(errorHandler);

app.listen(PORT, () => {
  logger.info(`Nexus backend running at http://localhost:${PORT}`);
});

// Initialize background jobs (scheduler will attempt missed snapshots on startup)
try {
  // require after server is listening
  const monthlyJob = require('./jobs/monthlySnapshot');
  monthlyJob.initScheduler();
} catch (err) {
  logger.error('Failed to start monthly snapshot job', err.message || err);
}

module.exports = app;
