// src/routes/system.routes.ts
// All route handlers now use req.log (request-scoped logger) as per ADR-004
import { Router, Request, Response, NextFunction } from 'express';
// Removed: import { logger } from '../services/logger.server';
// All route handlers now use req.log (request-scoped logger) as per ADR-004
import { geocodingService } from '../services/geocodingService.server';
// All route handlers now use req.log (request-scoped logger) as per ADR-004
import { validateRequest } from '../middleware/validation.middleware';
// All route handlers now use req.log (request-scoped logger) as per ADR-004
import { z } from 'zod';
// All route handlers now use req.log (request-scoped logger) as per ADR-004
import { requiredString } from '../utils/zodUtils';
// All route handlers now use req.log (request-scoped logger) as per ADR-004
import { systemService } from '../services/systemService';
// All route handlers now use req.log (request-scoped logger) as per ADR-004
import { geocodeLimiter } from '../config/rateLimiters';
import { sendSuccess, sendError, ErrorCode } from '../utils/apiResponse';

const router = Router();

const geocodeSchema = z.object({
  body: z.object({
    address: requiredString('An address string is required.'),
  }),
});

// An empty schema for routes that do not expect any input, to maintain a consistent validation pattern.
const emptySchema = z.object({});

/**
 * @openapi
 * /system/pm2-status:
 *   get:
 *     tags: [System]
 *     summary: Get PM2 process status
 *     description: Checks the status of the 'flyer-crawler-api' process managed by PM2. For development and diagnostic purposes.
 *     responses:
 *       200:
 *         description: PM2 process status information
 *         content:
 *           application/json:
 *             schema:
 *               $ref: '#/components/schemas/SuccessResponse'
 */
router.get(
  '/pm2-status',
  validateRequest(emptySchema),
  async (req: Request, res: Response, next: NextFunction) => {
    try {
      const status = await systemService.getPm2Status();
      sendSuccess(res, status);
    } catch (error) {
      next(error);
    }
  },
);

/**
 * @openapi
 * /system/geocode:
 *   post:
 *     tags: [System]
 *     summary: Geocode an address
 *     description: Geocodes a given address string. Acts as a secure proxy to the Google Maps Geocoding API.
 *     requestBody:
 *       required: true
 *       content:
 *         application/json:
 *           schema:
 *             type: object
 *             required:
 *               - address
 *             properties:
 *               address:
 *                 type: string
 *                 description: Address string to geocode
 *     responses:
 *       200:
 *         description: Geocoded coordinates
 *         content:
 *           application/json:
 *             schema:
 *               $ref: '#/components/schemas/SuccessResponse'
 *       404:
 *         description: Could not geocode the provided address
 */
router.post(
  '/geocode',
  geocodeLimiter,
  validateRequest(geocodeSchema),
  async (req: Request, res: Response, next: NextFunction) => {
    // Infer type and cast request object as per ADR-003
    type GeocodeRequest = z.infer<typeof geocodeSchema>;
    const {
      body: { address },
    } = req as unknown as GeocodeRequest;

    try {
      const coordinates = await geocodingService.geocodeAddress(address, req.log);

      if (!coordinates) {
        // This check remains, but now it only fails if BOTH services fail.
        return sendError(res, ErrorCode.NOT_FOUND, 'Could not geocode the provided address.', 404);
      }

      sendSuccess(res, coordinates);
    } catch (error) {
      req.log.error({ error }, 'Error geocoding address');
      next(error);
    }
  },
);

export default router;
