import { Router, Request, Response, NextFunction } from 'express';
import { randomUUID } from 'crypto';
import { authenticate } from '../../../middleware/auth.middleware';
import { requireRole } from '../../../middleware/rbac.middleware';
import { validate } from '../../../middleware/validate';
import { areaImportPreviewSchema, areaImportStartSchema } from './area-import.schemas';
import { areaImportService, type AreaImportProgress } from './area-import.service';
import { redis } from '../../../config/redis';
import { logger } from '../../../utils/logger';
import { MAP_ROLES } from '../../../utils/roles';

const areaImportRouter = Router();
areaImportRouter.use(authenticate);
areaImportRouter.use(requireRole(...MAP_ROLES));

// POST /api/map/area-import/preview — get bounds, estimates, and existing count
areaImportRouter.post(
  '/preview',
  validate(areaImportPreviewSchema),
  async (req: Request, res: Response, next: NextFunction) => {
    try {
      const result = await areaImportService.previewAreaImport(req.body);
      res.json(result);
    } catch (err) {
      next(err);
    }
  },
);

// POST /api/map/area-import — start import (fire-and-forget, returns importId)
areaImportRouter.post(
  '/',
  validate(areaImportStartSchema),
  async (req: Request, res: Response, next: NextFunction) => {
    try {
      const importId = randomUUID();
      const userId = req.user!.id;

      // Write initial progress so status endpoint works immediately
      const initialProgress: AreaImportProgress = {
        status: 'initializing',
        bounds: null,
        areaSqKm: 0,
        sources: {
          osm: { status: 'pending', candidatesFound: 0 },
          nar: { status: 'pending', candidatesFound: 0 },
          reverseGeocode: { status: 'pending', candidatesFound: 0 },
        },
        locationsCreated: 0,
        addressesCreated: 0,
        skippedDuplicate: 0,
        totalCandidates: 0,
      };
      await redis.set(`area-import:${importId}`, JSON.stringify(initialProgress), 'EX', 3600);

      // Fire and forget
      areaImportService.runAreaImport(userId, req.body, importId).catch((err) => {
        const errorMsg = err instanceof Error ? err.message : 'Unknown error';
        logger.error(`Area import ${importId} failed: ${errorMsg}`);
      });

      res.json({ importId });
    } catch (err) {
      next(err);
    }
  },
);

// GET /api/map/area-import/status/:importId — poll import progress
areaImportRouter.get(
  '/status/:importId',
  async (req: Request, res: Response, next: NextFunction) => {
    try {
      const importId = req.params.importId as string;
      const progress = await areaImportService.getProgress(importId);
      if (!progress) {
        res.status(404).json({ error: { message: 'Import not found or expired', code: 'NOT_FOUND' } });
        return;
      }
      res.json(progress);
    } catch (err) {
      next(err);
    }
  },
);

export { areaImportRouter };
