import { Router, Request, Response, NextFunction } from 'express';
import { z } from 'zod';
import { randomUUID } from 'crypto';
import { narImportService, writeProgress } from './nar-import.service';
import { redis } from '../../../config/redis';
import { logger } from '../../../utils/logger';
import { authenticate } from '../../../middleware/auth.middleware';
import { requireRole } from '../../../middleware/rbac.middleware';
import { validate } from '../../../middleware/validate';
import { MAP_ROLES } from '../../../utils/roles';

const serverImportSchema = z.object({
  provinceCode: z.string().min(1).max(2),
  filterType: z.enum(['none', 'city', 'postalPrefix', 'cut']).default('none'),
  filterCity: z.string().optional(),
  filterPostalPrefix: z.string().min(3).max(3).optional(),
  cutId: z.string().optional(),
  residentialOnly: z.boolean().default(true),
  deduplicateRadius: z.number().min(0).max(100).default(5),
  batchSize: z.number().int().min(100).max(5000).default(1000),
});

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

// GET /api/map/nar-import/datasets — list available NAR datasets by province
narImportRouter.get(
  '/datasets',
  async (_req: Request, res: Response, next: NextFunction) => {
    try {
      const result = await narImportService.listDatasets();
      res.json(result);
    } catch (err) {
      next(err);
    }
  }
);

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

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

      // Write initial progress so status endpoint works immediately
      await writeProgress(importId, {
        status: 'loading-locations',
        totalRows: 0,
        locationsCreated: 0,
        addressesCreated: 0,
        skippedDuplicate: 0,
        skippedOutOfBounds: 0,
        skippedNonResidential: 0,
        skippedInvalid: 0,
        currentFile: '',
        provinceName: '',
      });

      // Fire and forget — errors are written to Redis
      narImportService.importProvince(userId, req.body, importId).catch(async (err) => {
        const errorMsg = err instanceof Error ? err.message : 'Unknown error';
        logger.error(`NAR import ${importId} failed: ${errorMsg}`);
        await writeProgress(importId, {
          status: 'failed',
          totalRows: 0,
          locationsCreated: 0,
          addressesCreated: 0,
          skippedDuplicate: 0,
          skippedOutOfBounds: 0,
          skippedNonResidential: 0,
          skippedInvalid: 0,
          currentFile: '',
          provinceName: '',
          error: errorMsg,
        });
      });

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

export { narImportRouter };
