import express from 'express'
import { hasVisitorConsent } from './server/helpers.js'
import { BACKUP_INTERVAL_MS } from './server/config.js'
import { state } from './server/state.js'
import {
  loadHitStatsFromDisk,
  loadVisitorStatsFromDisk,
  loadContactSubmissionsFromDisk,
  loadReplyTemplatesFromDisk,
  loadReplyHistoryFromDisk,
  loadQuestionsFromDisk,
  loadDraftQuestionsFromDisk,
  loadStudyUsersFromDisk,
  loadStudyCommunityFromDisk,
  loadStudyRemindersFromDisk,
  migrateStudyNotesIfNeeded,
  loadDownloadCountsFromDisk,
  loadPodcastChecklistFromDisk,
  createBackupSnapshot,
  refreshContentCaches,
  queueHitStatsWrite,
} from './server/data.js'
import { logResendEmailAlignmentWarnings, sendStudyReminderEmail } from './server/email.js'
import {
  detectBot,
  sanitizeUserAgent,
  shouldCountHit,
  recordHit,
  scheduleStudyReminders,
} from './server/study-helpers.js'
import { recordVisitor } from './server/routes/analytics.js'

// Route registrars
import { register as registerAdminAuth } from './server/routes/admin-auth.js'
import { register as registerAdminContent } from './server/routes/admin-content.js'
import { register as registerAdminAssets } from './server/routes/admin-assets.js'
import { register as registerStudyAuth } from './server/routes/study-auth.js'
import { register as registerStudyData } from './server/routes/study-data.js'
import { register as registerStudyAccount } from './server/routes/study-account.js'
import { register as registerContact } from './server/routes/contact.js'
import { register as registerQuestions } from './server/routes/questions.js'
import { register as registerAnalytics } from './server/routes/analytics.js'
import { register as registerDownloads } from './server/routes/downloads.js'
import { register as registerEpisodes } from './server/routes/episodes.js'
import { register as registerPublic } from './server/routes/public.js'

const app = express()
app.use(express.json({ limit: '10mb' }))
const trustProxyHops = Number(process.env.TRUST_PROXY_HOPS ?? 1)
app.set('trust proxy', Number.isFinite(trustProxyHops) && trustProxyHops >= 0 ? trustProxyHops : 1)

// Register API routes
registerAdminAuth(app)
registerAdminContent(app)
registerAdminAssets(app)
registerStudyAuth(app)
registerStudyData(app)
registerStudyAccount(app)
registerContact(app)
registerQuestions(app)
registerAnalytics(app)
registerDownloads(app)
registerEpisodes(app)

// Hit-counting middleware (must come before public routes)
app.use((req, res, next) => {
  if (shouldCountHit(req)) {
    const ua = sanitizeUserAgent(req.get('user-agent'))
    const botDetection = detectBot(ua)
    recordHit(req.path, botDetection.isBot, botDetection.reason)
    queueHitStatsWrite()
    if (hasVisitorConsent(req) && !botDetection.isBot) {
      recordVisitor(req, res).catch(err => {
        console.error('[visitor-stats] failed to record visitor:', err)
      })
    }
  }
  next()
})

// Public routes (robots, sitemap, static, SPA fallback)
registerPublic(app)

const PORT = Number(process.env.PORT ?? 4173)
Promise.all([
  loadHitStatsFromDisk(),
  loadVisitorStatsFromDisk(),
  loadContactSubmissionsFromDisk(),
  loadReplyTemplatesFromDisk(),
  loadReplyHistoryFromDisk(),
  loadQuestionsFromDisk(),
  loadDraftQuestionsFromDisk(),
  loadStudyUsersFromDisk(),
  loadStudyCommunityFromDisk(),
  loadStudyRemindersFromDisk(),
  migrateStudyNotesIfNeeded(),
  loadDownloadCountsFromDisk(),
  loadPodcastChecklistFromDisk(),
  refreshContentCaches(),
])
  .catch(err => {
    console.error('[stats] failed to load persisted stats:', err)
  })
  .finally(() => {
    createBackupSnapshot('startup').catch(() => {})
    setInterval(() => {
      createBackupSnapshot('scheduled').catch(() => {})
    }, BACKUP_INTERVAL_MS)

    // Purge expired study sessions every hour
    setInterval(() => {
      const now = Date.now()
      for (const [token, session] of state.studySessions) {
        if (session.expiresAt <= now) state.studySessions.delete(token)
      }
    }, 60 * 60 * 1000)

    // Send study reminder emails for newly released lessons every hour
    setInterval(() => {
      scheduleStudyReminders(sendStudyReminderEmail).catch(err => {
        console.error('[study-reminders] failed to schedule reminders:', err)
      })
    }, 60 * 60 * 1000)
    void scheduleStudyReminders(sendStudyReminderEmail)

    app.listen(PORT, () => {
      logResendEmailAlignmentWarnings()
      console.log(`Portfolio app listening on http://localhost:${PORT}`)
    })
  })
