/**
 * Translation Routes
 *
 * Synchronous translation endpoint (for content up to 5000 characters)
 */

import { Router, Request, Response } from 'express';
import { z } from 'zod';
import { authenticateApiKey } from '../middleware/auth';
import { apiRateLimiter } from '../middleware/rateLimiter';
import { validate } from '../middleware/validator';
import { transformWordPressJobPayload } from '../middleware/payloadTransform';
import { translationService } from '../services/translationService';
import { logger } from '../utils/logger';
import { LanguageCodeSchema, ToneSchema } from '../types';
import { ExceptionRulesSchema } from '../services/exceptionService';
import {
  BULK_REQUEST_CHAR_BUDGET,
  BULK_SYNC_MAX_STRINGS,
  BULK_MAX_CHARS_PER_STRING,
} from '../config/batchLimits';

const router = Router();

// Validation schema for synchronous translation request.
// Accepts either structured fields (title/excerpt/content) or a single content blob.
const translateSchema = z.object({
  sourceLang: LanguageCodeSchema,
  targetLang: LanguageCodeSchema,
  title: z.string().max(5000).optional(),
  excerpt: z.string().max(5000).optional(),
  content: z.string().max(5000, 'Content must not exceed 5000 characters for synchronous translation').optional(),
  tone: ToneSchema.optional(),
  exceptions: ExceptionRulesSchema,
  clientJobId: z.string().optional(),
}).refine(
  (data) => data.title || data.excerpt || data.content,
  { message: 'At least one of title, excerpt, or content must be provided' }
);

/**
 * POST /v1/translate
 * Synchronous translation (up to 5000 characters)
 *
 * @requires API Key authentication
 * @requires Rate limiting based on subscription tier
 */
router.post(
  '/',
  transformWordPressJobPayload,
  authenticateApiKey,
  apiRateLimiter,
  validate(translateSchema),
  async (req: Request, res: Response) => {
    try {
      const userId = req.user!.userId;
      const translationRequest = req.body;

      const contentLength = (translationRequest.title?.length || 0) +
        (translationRequest.excerpt?.length || 0) +
        (translationRequest.content?.length || 0);

      logger.info('Sync translation request received', {
        userId,
        sourceLang: translationRequest.sourceLang,
        targetLang: translationRequest.targetLang,
        contentLength,
        isStructured: !!(translationRequest.title !== undefined || translationRequest.excerpt !== undefined),
      });

      // Call translation service
      const result = await translationService.translateSync(userId, translationRequest, req.user!.plugin);

      // Return flat structure for WordPress PHP compatibility
      return res.status(200).json({
        success: true,
        translation: result.translation,
        translated_title: result.translatedTitle,
        translated_excerpt: result.translatedExcerpt,
        translated_content: result.translatedContent,
        characters_used: result.charactersUsed,
        cost_usd: result.customerCost,
        job_id: result.jobId,
        status: result.status,
        processing_time_ms: result.processingTimeMs,
        data: result,
        timestamp: new Date().toISOString(),
      });
    } catch (error) {
      logger.error('Sync translation error', {
        error,
        userId: req.user?.userId,
        requestId: req.requestId,
      });

      const errorMessage = error instanceof Error ? error.message : 'Unknown error occurred';

      // Handle insufficient credits error
      if (errorMessage.includes('Insufficient credits')) {
        return res.status(402).json({
          error: true,
          code: 'INSUFFICIENT_CREDITS',
          message: errorMessage,
          timestamp: new Date().toISOString(),
        });
      }

      // Handle content too long error
      if (errorMessage.includes('Content too long')) {
        return res.status(413).json({
          error: true,
          code: 'CONTENT_TOO_LONG',
          message: errorMessage,
          timestamp: new Date().toISOString(),
        });
      }

      // Handle translation failure
      if (errorMessage.includes('Translation failed')) {
        return res.status(500).json({
          error: true,
          code: 'TRANSLATION_FAILED',
          message: errorMessage,
          timestamp: new Date().toISOString(),
        });
      }

      // Generic error
      return res.status(500).json({
        error: true,
        code: 'INTERNAL_ERROR',
        message: 'An internal error occurred while processing the translation',
        timestamp: new Date().toISOString(),
      });
    }
  }
);

// Validation schema for bulk synchronous translation request
const bulkTranslateSchema = z.object({
  sourceLang: LanguageCodeSchema,
  targetLang: LanguageCodeSchema,
  strings: z.array(z.object({
    id: z.string().min(1),
    content: z.string().min(1).max(
      BULK_MAX_CHARS_PER_STRING,
      `Each string must not exceed ${BULK_MAX_CHARS_PER_STRING} characters`
    ),
  })).min(1).max(
    BULK_SYNC_MAX_STRINGS,
    `Bulk translation supports at most ${BULK_SYNC_MAX_STRINGS} strings per request`
  ),
  tone: ToneSchema.optional(),
  exceptions: ExceptionRulesSchema,
}).refine(
  (data) => data.strings.reduce((total, string) => total + string.content.length, 0) <= BULK_REQUEST_CHAR_BUDGET,
  {
    path: ['strings'],
    message: `Total bulk string content must not exceed ${BULK_REQUEST_CHAR_BUDGET} characters per request`,
  }
);

/**
 * POST /v1/translate/bulk
 * Synchronous bulk translation — requests are limited by shared character and count budgets
 *
 * @requires API Key authentication
 * @requires Rate limiting based on subscription tier
 */
router.post(
  '/bulk',
  transformWordPressJobPayload,
  authenticateApiKey,
  apiRateLimiter,
  validate(bulkTranslateSchema),
  async (req: Request, res: Response) => {
    try {
      const userId = req.user!.userId;

      logger.info('Bulk sync translation request received', {
        userId,
        sourceLang: req.body.sourceLang,
        targetLang: req.body.targetLang,
        stringCount: req.body.strings.length,
      });

      // Keep one service invocation for the whole request: it owns the single
      // balance check, job record, deduction, and internal Gemini batch loop.
      // Splitting here would repeat request-level accounting for every batch.
      const result = await translationService.translateBulkSync(userId, req.body, req.user!.plugin);

      return res.status(200).json({
        success: true,
        results: result.results,
        total_characters_used: result.totalCharactersUsed,
        total_strings: req.body.strings.length,
        failed_count: result.failedCount,
        timestamp: new Date().toISOString(),
      });
    } catch (error) {
      logger.error('Bulk sync translation error', {
        error,
        userId: req.user?.userId,
        requestId: req.requestId,
      });

      const errorMessage = error instanceof Error ? error.message : 'Unknown error occurred';

      if (errorMessage.includes('Insufficient credits')) {
        return res.status(402).json({
          error: true,
          code: 'INSUFFICIENT_CREDITS',
          message: errorMessage,
          timestamp: new Date().toISOString(),
        });
      }

      return res.status(500).json({
        error: true,
        code: 'TRANSLATION_FAILED',
        message: 'An internal error occurred while processing the bulk translation',
        timestamp: new Date().toISOString(),
      });
    }
  }
);

export default router;
