import { Request, Response } from 'express';
import { container } from 'tsyringe';
import { z } from 'zod';
import { NLPService } from '../../services/nlp/nlp.service';
import { TranslationService } from '../../services/nlp/translation.service';
import { LanguageDetectorService } from '../../services/nlp/language-detector.service';

/**
 * Request schemas for NLP endpoints
 */
const ParseRequestSchema = z.object({
  text: z.string().min(1).max(10000),
  language: z.string().optional(),
  projectId: z.string().optional(),
  userId: z.string().optional(),
  context: z.record(z.string(), z.any()).optional(),
});

const ExtractEntitiesRequestSchema = z.object({
  text: z.string().min(1).max(10000),
  language: z.string().optional(),
  context: z.record(z.string(), z.any()).optional(),
});

const ClassifyRequestSchema = z.object({
  text: z.string().min(1).max(10000),
  language: z.string().optional(),
  entities: z.object({
    title: z.string().optional(),
    description: z.string().optional(),
    priority: z.enum(['critical', 'high', 'medium', 'low']).optional(),
    deadline: z.union([z.date(), z.string()]).optional(),
    estimatedHours: z.number().optional(),
    assignees: z.array(z.string()).optional(),
    dependencies: z.array(z.string()).optional(),
    tags: z.array(z.string()).optional(),
  }).optional(),
});

const TranslateRequestSchema = z.object({
  text: z.string().min(1).max(10000),
  sourceLanguage: z.string().optional(),
  targetLanguage: z.string(),
  preserveFormatting: z.boolean().optional(),
  context: z.string().optional(),
});

const DetectLanguageRequestSchema = z.object({
  text: z.string().min(1).max(5000),
});

/**
 * NLP Controller for natural language processing endpoints
 */
export class NLPController {
  private nlpService: NLPService;
  private translationService: TranslationService;
  private languageDetector: LanguageDetectorService;

  constructor() {
    this.nlpService = container.resolve(NLPService);
    this.translationService = container.resolve(TranslationService);
    this.languageDetector = container.resolve(LanguageDetectorService);
  }

  /**
   * POST /api/nlp/parse
   * Parse natural language text into structured task data
   */
  async parse(req: Request, res: Response): Promise<void> {
    try {
      const validated = ParseRequestSchema.parse(req.body);
      
      const result = await this.nlpService.processTextWithTranslation({
        text: validated.text,
        language: validated.language,
        projectId: validated.projectId,
        userId: validated.userId,
        context: validated.context,
      });

      res.json({
        success: result.success,
        data: {
          entities: result.entities,
          classification: result.classification,
          structuredData: result.structuredData,
          language: result.language,
        },
        metadata: {
          processingTime: result.processingTime,
          tokensUsed: result.tokensUsed,
          errors: result.errors,
        },
      });
    } catch (error) {
      if (error instanceof z.ZodError) {
        res.status(400).json({
          success: false,
          error: 'Validation Error',
          details: error.issues,
        });
      } else {
        console.error('NLP parse error:', error);
        res.status(500).json({
          success: false,
          error: 'Failed to parse text',
          message: error instanceof Error ? error.message : 'Unknown error',
        });
      }
    }
  }

  /**
   * POST /api/nlp/extract-entities
   * Extract entities from natural language text
   */
  async extractEntities(req: Request, res: Response): Promise<void> {
    try {
      const validated = ExtractEntitiesRequestSchema.parse(req.body);
      
      const result = await this.nlpService.processText({
        text: validated.text,
        language: validated.language,
        context: validated.context,
      });

      res.json({
        success: result.success,
        data: {
          entities: result.entities,
        },
        metadata: {
          language: result.language,
          processingTime: result.processingTime,
          confidence: result.entities.confidence,
        },
      });
    } catch (error) {
      if (error instanceof z.ZodError) {
        res.status(400).json({
          success: false,
          error: 'Validation Error',
          details: error.issues,
        });
      } else {
        console.error('Entity extraction error:', error);
        res.status(500).json({
          success: false,
          error: 'Failed to extract entities',
          message: error instanceof Error ? error.message : 'Unknown error',
        });
      }
    }
  }

  /**
   * POST /api/nlp/classify
   * Classify task type and attributes
   */
  async classify(req: Request, res: Response): Promise<void> {
    try {
      const validated = ClassifyRequestSchema.parse(req.body);
      
      const result = await this.nlpService.processText({
        text: validated.text,
        language: validated.language,
        context: { entities: validated.entities },
      });

      res.json({
        success: result.success,
        data: {
          classification: result.classification,
        },
        metadata: {
          language: result.language,
          processingTime: result.processingTime,
          confidence: result.classification.confidence,
        },
      });
    } catch (error) {
      if (error instanceof z.ZodError) {
        res.status(400).json({
          success: false,
          error: 'Validation Error',
          details: error.issues,
        });
      } else {
        console.error('Classification error:', error);
        res.status(500).json({
          success: false,
          error: 'Failed to classify text',
          message: error instanceof Error ? error.message : 'Unknown error',
        });
      }
    }
  }

  /**
   * POST /api/nlp/translate
   * Translate text between languages
   */
  async translate(req: Request, res: Response): Promise<void> {
    try {
      const validated = TranslateRequestSchema.parse(req.body);
      
      const result = await this.translationService.translate({
        text: validated.text,
        sourceLanguage: validated.sourceLanguage,
        targetLanguage: validated.targetLanguage,
        preserveFormatting: validated.preserveFormatting,
        context: validated.context,
      });

      res.json({
        success: true,
        data: {
          originalText: result.originalText,
          translatedText: result.translatedText,
          sourceLanguage: result.sourceLanguage,
          targetLanguage: result.targetLanguage,
        },
        metadata: {
          confidence: result.confidence,
          alternatives: result.alternatives,
        },
      });
    } catch (error) {
      if (error instanceof z.ZodError) {
        res.status(400).json({
          success: false,
          error: 'Validation Error',
          details: error.issues,
        });
      } else {
        console.error('Translation error:', error);
        res.status(500).json({
          success: false,
          error: 'Failed to translate text',
          message: error instanceof Error ? error.message : 'Unknown error',
        });
      }
    }
  }

  /**
   * POST /api/nlp/detect-language
   * Detect the language of input text
   */
  async detectLanguage(req: Request, res: Response): Promise<void> {
    try {
      const validated = DetectLanguageRequestSchema.parse(req.body);
      
      const result = await this.languageDetector.detectLanguage(validated.text);

      res.json({
        success: true,
        data: {
          language: result.language,
          confidence: result.confidence,
        },
        metadata: {
          alternatives: result.alternatives,
        },
      });
    } catch (error) {
      if (error instanceof z.ZodError) {
        res.status(400).json({
          success: false,
          error: 'Validation Error',
          details: error.issues,
        });
      } else {
        console.error('Language detection error:', error);
        res.status(500).json({
          success: false,
          error: 'Failed to detect language',
          message: error instanceof Error ? error.message : 'Unknown error',
        });
      }
    }
  }

  /**
   * GET /api/nlp/languages
   * Get supported languages
   */
  async getSupportedLanguages(req: Request, res: Response): Promise<void> {
    try {
      const languages = this.languageDetector.getSupportedLanguages();
      
      res.json({
        success: true,
        data: {
          languages,
        },
      });
    } catch (error) {
      console.error('Get languages error:', error);
      res.status(500).json({
        success: false,
        error: 'Failed to get supported languages',
        message: error instanceof Error ? error.message : 'Unknown error',
      });
    }
  }

  /**
   * GET /api/nlp/cache/stats
   * Get NLP cache statistics
   */
  async getCacheStats(req: Request, res: Response): Promise<void> {
    try {
      const nlpStats = this.nlpService.getCacheStats();
      const translationStats = this.translationService.getCacheStats();
      
      res.json({
        success: true,
        data: {
          nlpCache: nlpStats,
          translationCache: translationStats,
        },
      });
    } catch (error) {
      console.error('Get cache stats error:', error);
      res.status(500).json({
        success: false,
        error: 'Failed to get cache statistics',
        message: error instanceof Error ? error.message : 'Unknown error',
      });
    }
  }

  /**
   * DELETE /api/nlp/cache
   * Clear NLP caches
   */
  async clearCache(req: Request, res: Response): Promise<void> {
    try {
      this.nlpService.clearCache();
      this.translationService.clearCache();
      
      res.json({
        success: true,
        message: 'Cache cleared successfully',
      });
    } catch (error) {
      console.error('Clear cache error:', error);
      res.status(500).json({
        success: false,
        error: 'Failed to clear cache',
        message: error instanceof Error ? error.message : 'Unknown error',
      });
    }
  }
}