import { Router, Request, Response, NextFunction } from 'express';
import { UserRole } from '@prisma/client';
import { siteSettingsService } from './settings.service';
import { updateSiteSettingsSchema } from './settings.schemas';
import { validate } from '../../middleware/validate';
import { authenticate } from '../../middleware/auth.middleware';
import { requireRole } from '../../middleware/rbac.middleware';
import { emailService } from '../../services/email.service';
import { giteaClient } from '../../services/gitea.client';
import { gancioSettingsSyncService } from '../../services/gancio-settings-sync.service';
import { autoUpgradeService } from '../../services/auto-upgrade.service';
import { headerBuilderService } from '../docs/header-builder.service';
import { mkdocsConfigService } from '../docs/mkdocs-config.service';
import { logger } from '../../utils/logger';

const router = Router();

// GET /api/settings — public (needed by login page + public pages), strips SMTP credentials
router.get(
  '/',
  async (_req: Request, res: Response, next: NextFunction) => {
    try {
      const settings = await siteSettingsService.getPublic();
      res.json(settings);
    } catch (err) {
      next(err);
    }
  }
);

// GET /api/settings/admin — SUPER_ADMIN only, returns full settings including SMTP
router.get(
  '/admin',
  authenticate,
  requireRole(UserRole.SUPER_ADMIN),
  async (_req: Request, res: Response, next: NextFunction) => {
    try {
      const settings = await siteSettingsService.getEffective();
      res.set('Cache-Control', 'no-store');
      res.json(settings);
    } catch (err) {
      next(err);
    }
  }
);

// POST /api/settings/email/test-connection — SUPER_ADMIN only
router.post(
  '/email/test-connection',
  authenticate,
  requireRole(UserRole.SUPER_ADMIN),
  async (_req: Request, res: Response, next: NextFunction) => {
    try {
      const success = await emailService.testConnection();
      res.json({ success, message: success ? 'SMTP connection verified' : 'SMTP connection failed' });
    } catch (err) {
      next(err);
    }
  }
);

// POST /api/settings/email/test-send — SUPER_ADMIN only
router.post(
  '/email/test-send',
  authenticate,
  requireRole(UserRole.SUPER_ADMIN),
  async (req: Request, res: Response, next: NextFunction) => {
    try {
      const { to } = req.body as { to?: string };
      const settings = await siteSettingsService.get();
      const recipient = to || settings.testEmailRecipient || 'admin@cmlite.org';

      const result = await emailService.sendEmail({
        to: recipient,
        subject: 'Changemaker Lite — Test Email',
        html: `<h2>SMTP Test Successful</h2><p>This email confirms that your SMTP configuration is working correctly.</p><p>Sent at: ${new Date().toISOString()}</p>`,
        text: `SMTP Test Successful\n\nThis email confirms that your SMTP configuration is working correctly.\n\nSent at: ${new Date().toISOString()}`,
      });

      res.json({
        success: result.success,
        messageId: result.messageId,
        testMode: result.testMode,
        recipient,
      });
    } catch (err) {
      next(err);
    }
  }
);

// PUT /api/settings — SUPER_ADMIN only
router.put(
  '/',
  authenticate,
  requireRole(UserRole.SUPER_ADMIN),
  validate(updateSiteSettingsSchema),
  async (req: Request, res: Response, next: NextFunction) => {
    try {
      const settings = await siteSettingsService.update(req.body);

      // If SMTP-related fields were updated, rebuild the transporter
      const smtpFields = ['smtpHost', 'smtpPort', 'smtpUser', 'smtpPass', 'smtpFromAddress', 'smtpActiveProvider', 'emailTestMode', 'testEmailRecipient'];
      const hasSmtpChanges = smtpFields.some((f) => f in req.body);
      if (hasSmtpChanges) {
        await emailService.rebuildTransporter();
      }

      // If Gitea-related fields were updated, invalidate the config cache
      const giteaFields = ['enableDocsComments', 'giteaApiToken', 'giteaCommentsRepoOwner', 'giteaCommentsRepoName', 'giteaOauthClientId', 'giteaOauthClientSecret'];
      if (giteaFields.some((f) => f in req.body)) {
        giteaClient.clearConfigCache();
      }

      // If Gancio-relevant fields were updated, sync to Gancio (fire-and-forget)
      if (gancioSettingsSyncService.hasGancioChanges(req.body)) {
        gancioSettingsSyncService.syncChanged(req.body).catch(() => {});
      }

      // If auto-upgrade settings changed, restart the scheduler
      const autoUpgradeFields = ['enableAutoUpgrade', 'autoUpgradeSchedule', 'autoUpgradePullServices'];
      if (autoUpgradeFields.some((f) => f in req.body)) {
        autoUpgradeService.start().catch(() => {});
      }

      // If navConfig or theme colors changed, trigger MkDocs header rebuild + docs build
      const headerTriggerFields = [
        'navConfig', 'publicHeaderGradient', 'publicColorBgBase', 'publicColorBgContainer',
        'enableInfluence', 'enableMap', 'enableMediaFeatures', 'enablePayments',
        'enableEvents', 'enableMeetingPlanner', 'enableTicketedEvents', 'enableSocial',
        'enableMeet', 'enableLandingPages',
      ];
      if (headerTriggerFields.some((f) => f in req.body)) {
        if ('navConfig' in req.body) {
          gancioSettingsSyncService.syncAll().catch(() => {});
        }
        // Regenerate MkDocs header from navConfig, then trigger a docs build
        const navItems = (settings.navConfig as Record<string, unknown> | null)?.items as unknown[] | undefined;
        if (navItems?.length) {
          headerBuilderService.regenerateFromNavConfig(
            navItems as any[],
            {
              publicHeaderGradient: settings.publicHeaderGradient ?? undefined,
              publicColorBgBase: settings.publicColorBgBase ?? undefined,
              publicColorBgContainer: settings.publicColorBgContainer ?? undefined,
              enableInfluence: settings.enableInfluence,
              enableMap: settings.enableMap,
              enableMediaFeatures: settings.enableMediaFeatures,
              enablePayments: settings.enablePayments,
              enableEvents: settings.enableEvents,
              enableMeetingPlanner: settings.enableMeetingPlanner,
              enableTicketedEvents: settings.enableTicketedEvents,
              enableSocial: settings.enableSocial,
              enableMeet: settings.enableMeet,
              enableLandingPages: settings.enableLandingPages,
            },
          ).then(() => {
            // Fire-and-forget docs build so the static site picks up the new header
            mkdocsConfigService.triggerBuild()
              .then((result) => {
                if (result.success) {
                  logger.info(`MkDocs rebuild after header change completed in ${result.duration}ms`);
                } else {
                  logger.warn(`MkDocs rebuild after header change failed: ${result.output}`);
                }
              })
              .catch(() => {});
          }).catch(() => {});
        }
      }

      res.json(settings);
    } catch (err) {
      next(err);
    }
  }
);

export { router as siteSettingsRouter };
