import {
  Body,
  Controller,
  Delete,
  Get,
  NotFoundException,
  Param,
  ParseUUIDPipe,
  Post,
  Put,
  Query,
  Request,
  UploadedFile,
  UseInterceptors,
} from '@nestjs/common';
import { FileInterceptor } from '@nestjs/platform-express';
import * as os from 'os';
import * as path from 'path';
import { randomUUID } from 'crypto';
import * as fs from 'fs';

type MulterFile = {
  originalname: string;
  path: string;
};

// eslint-disable-next-line @typescript-eslint/no-var-requires
const { diskStorage } = require('multer');
import {
  CreateKnowledgeArticleDto,
  UpdateKnowledgeArticleDto,
} from './dto/knowledge-article.dto';
import { KnowledgeBaseService } from './knowledge-base.service';
import { KnowledgeArticleService } from './knowledge-article.service';
import { RagflowSearchService } from './services/ragflow-search.service';
import { KnowledgeQaService } from './services/knowledge-qa.service';
import { MetricsService } from './services/metrics.service';
import { ActivityService } from './services/activity.service';
import { SearchSuggestionService } from './services/search-suggestion.service';
import { SyncSchedulerTask } from './tasks/sync-scheduler.task';
import { RagflowSyncService } from './services/ragflow-sync.service';

@Controller('knowledge-base')
export class KnowledgeBaseController {
  constructor(
    private readonly knowledgeBaseService: KnowledgeBaseService,
    private readonly knowledgeArticleService: KnowledgeArticleService,
    private readonly searchService: RagflowSearchService,
    private readonly qaService: KnowledgeQaService,
    private readonly metricsService: MetricsService,
    private readonly activityService: ActivityService,
    private readonly searchSuggestionService: SearchSuggestionService,
    private readonly syncScheduler: SyncSchedulerTask,
    private readonly ragflowSyncService: RagflowSyncService,
  ) {}

  /**
   * 搜索输入联想建议
   */
  @Get('search-suggestions')
  async searchSuggestions(
    @Request() req: any,
    @Query('q') query: string,
    @Query('limit') limit?: number,
  ) {
    const suggestions = await this.searchSuggestionService.suggest(
      req.user.userId,
      query,
      limit ? parseInt(String(limit), 10) : 8,
    );
    return {
      items: suggestions,
    };
  }

  /**
   * 删除最近搜索（单条/全部）
   */
  @Delete('search-history')
  async deleteSearchHistory(
    @Request() req: any,
    @Query('query') query?: string,
  ) {
    const deleted = query?.trim()
      ? await this.searchSuggestionService.removeRecentSearch(
          req.user.userId,
          query,
        )
      : await this.searchSuggestionService.clearRecentSearches(req.user.userId);

    return { deleted };
  }

  /**
   * 语义搜索（支持关键词、语义、混合模式）
   */
  @Get('semantic-search')
  async semanticSearch(
    @Request() req: any,
    @Query('q') query: string,
    @Query('limit') limit?: number,
  ) {
    return this.searchService.search(
      req.user.userId,
      query,
      limit ? parseInt(String(limit), 10) : 20,
    );
  }

  // ============================================================================
  // AI 问答 (RAG)
  // ============================================================================

  /**
   * AI 问答
   */
  @Post('ask')
  async ask(@Request() req: any, @Body() body: { question: string }) {
    return this.qaService.ask(body.question, req.user.userId);
  }

  /**
   * 提交问答反馈
   */
  @Post('ask/:id/feedback')
  async submitFeedback(
    @Param('id', ParseUUIDPipe) id: string,
    @Body() body: { feedback: 'THUMBS_UP' | 'THUMBS_DOWN'; comment?: string },
  ) {
    await this.qaService.submitFeedback(id, body.feedback, body.comment);
    return { data: { success: true }, message: '反馈已提交' };
  }

  /**
   * 获取问答历史
   */
  @Get('ask/history')
  async getAskHistory(@Request() req: any, @Query('limit') limit?: number) {
    const history = await this.qaService.getUserHistory(
      req.user.userId,
      limit ? parseInt(String(limit), 10) : 20,
    );
    return { items: history };
  }

  @Post('upload')
  @UseInterceptors(
    FileInterceptor('file', {
      storage: diskStorage({
        destination: os.tmpdir(),
        filename: (
          _req: unknown,
          file: MulterFile,
          cb: (error: Error | null, filename: string) => void,
        ) => {
          const ext = path.extname(file.originalname || '');
          cb(null, `${Date.now()}-${randomUUID()}${ext}`);
        },
      }),
    }),
  )
  async upload(@UploadedFile() file?: MulterFile) {
    if (!file) {
      return {
        message: '未收到上传文件',
        data: null,
      };
    }

    const item = await this.knowledgeBaseService.uploadFile(
      file.path,
      file.originalname,
    );
    await this.safeRemove(file.path);
    return {
      item,
    };
  }

  @Post('articles')
  async createArticle(
    @Request() req: any,
    @Body() dto: CreateKnowledgeArticleDto,
  ) {
    return {
      data: await this.knowledgeArticleService.create(req.user.userId, dto),
      message: '文章创建成功',
    };
  }

  @Get('articles/:id')
  async getArticle(@Param('id', ParseUUIDPipe) id: string) {
    return this.knowledgeArticleService.findById(id);
  }

  @Put('articles/:id')
  async updateArticle(
    @Param('id', ParseUUIDPipe) id: string,
    @Body() dto: UpdateKnowledgeArticleDto,
  ) {
    return {
      data: await this.knowledgeArticleService.update(id, dto),
      message: '文章已保存',
    };
  }

  // ============================================================================
  // 同步管理 API
  // ============================================================================

  /**
   * 触发全量同步
   */
  @Post('sync/full')
  async triggerFullSync() {
    const taskId = await this.syncScheduler.triggerFullSync();
    return {
      taskId,
      message: '全量同步任务已启动',
    };
  }

  /**
   * 触发增量同步
   */
  @Post('sync/delta')
  async triggerDeltaSync() {
    const result = await this.syncScheduler.triggerDeltaSync();
    return {
      taskId: result.taskId,
      message: result.fallbackToFull
        ? '增量同步不可用，已切换为全量同步'
        : '增量同步任务已启动',
    };
  }

  /**
   * 获取同步任务列表
   */
  @Get('sync/tasks')
  async listSyncTasks(
    @Query('limit') limit?: number,
    @Query('offset') offset?: number,
  ) {
    const safeLimit = Math.min(Math.max(Number(limit ?? 20), 1), 100);
    const safeOffset = Math.max(Number(offset ?? 0), 0);
    return this.ragflowSyncService.listTasks(safeLimit, safeOffset);
  }

  /**
   * 获取同步任务跳过明细
   */
  @Get('sync/tasks/:taskId/skipped')
  async listSyncTaskSkippedItems(
    @Param('taskId', ParseUUIDPipe) taskId: string,
    @Query('limit') limit?: number,
    @Query('offset') offset?: number,
  ) {
    const safeLimit = Math.min(Math.max(Number(limit ?? 20), 1), 200);
    const safeOffset = Math.max(Number(offset ?? 0), 0);
    return this.ragflowSyncService.listSkippedItems(
      taskId,
      safeLimit,
      safeOffset,
    );
  }

  /**
   * 获取同步任务已处理明细
   */
  @Get('sync/tasks/:taskId/processed')
  async listSyncTaskProcessedItems(
    @Param('taskId', ParseUUIDPipe) taskId: string,
    @Query('limit') limit?: number,
    @Query('offset') offset?: number,
  ) {
    const safeLimit = Math.min(Math.max(Number(limit ?? 20), 1), 200);
    const safeOffset = Math.max(Number(offset ?? 0), 0);
    return this.ragflowSyncService.listProcessedItems(
      taskId,
      safeLimit,
      safeOffset,
    );
  }

  /**
   * 获取同步任务处理中明细
   */
  @Get('sync/tasks/:taskId/processing')
  async listSyncTaskProcessingItems(
    @Param('taskId', ParseUUIDPipe) taskId: string,
    @Query('limit') limit?: number,
    @Query('offset') offset?: number,
  ) {
    const safeLimit = Math.min(Math.max(Number(limit ?? 20), 1), 200);
    const safeOffset = Math.max(Number(offset ?? 0), 0);
    return this.ragflowSyncService.listProcessingItems(
      taskId,
      safeLimit,
      safeOffset,
    );
  }

  /**
   * 获取同步任务失败明细
   */
  @Get('sync/tasks/:taskId/failed')
  async listSyncTaskFailedItems(
    @Param('taskId', ParseUUIDPipe) taskId: string,
    @Query('limit') limit?: number,
    @Query('offset') offset?: number,
  ) {
    const safeLimit = Math.min(Math.max(Number(limit ?? 20), 1), 200);
    const safeOffset = Math.max(Number(offset ?? 0), 0);
    return this.ragflowSyncService.listFailedItems(
      taskId,
      safeLimit,
      safeOffset,
    );
  }

  /**
   * 获取同步任务状态
   */
  @Get('sync/tasks/:taskId')
  async getSyncTaskStatus(@Param('taskId', ParseUUIDPipe) taskId: string) {
    const status = await this.ragflowSyncService.getTaskStatus(taskId);
    if (!status) {
      throw new NotFoundException(`Sync task ${taskId} not found`);
    }
    return status;
  }

  /**
   * 手动终止同步任务
   */
  @Post('sync/tasks/:taskId/terminate')
  async terminateSyncTask(@Param('taskId', ParseUUIDPipe) taskId: string) {
    return this.ragflowSyncService.terminateSyncTask(taskId);
  }

  // ============================================================================
  // 度量与统计 API
  // ============================================================================

  /**
   * 获取度量概览
   */
  @Get('metrics')
  async getMetricsOverview() {
    const metrics = await this.metricsService.getMetricsOverview();
    return metrics;
  }

  /**
   * 获取每日趋势统计
   */
  @Get('metrics/trend')
  async getDailyTrend(@Query('days') days?: number) {
    const trend = await this.metricsService.getDailyTrend(
      days ? parseInt(String(days), 10) : 30,
    );
    return { items: trend };
  }

  /**
   * 获取搜索热词
   */
  @Get('metrics/top-queries')
  async getTopQueries(
    @Query('days') days?: number,
    @Query('limit') limit?: number,
  ) {
    const queries = await this.metricsService.getTopSearchQueries(
      days ? parseInt(String(days), 10) : 7,
      limit ? parseInt(String(limit), 10) : 10,
    );
    return { items: queries };
  }

  // ============================================================================
  // 活动与最近访问 API
  // ============================================================================

  /**
   * 获取最近访问的文档
   */
  @Get('recently-visited')
  async getRecentlyVisited(
    @Request() req: any,
    @Query('limit') limit?: number,
  ) {
    const items = await this.activityService.getRecentlyVisited(
      req.user.userId,
      limit ? parseInt(String(limit), 10) : 6,
    );
    return { items };
  }

  /**
   * 记录文档浏览
   */
  @Post('view/:type/:id')
  async recordView(
    @Request() req: any,
    @Param('type') type: 'document' | 'article',
    @Param('id', ParseUUIDPipe) id: string,
  ) {
    await this.activityService.recordView(req.user.userId, type, id);
    return { success: true };
  }

  /**
   * 获取活动动态
   */
  @Get('activity')
  async getActivityFeed(
    @Request() req: any,
    @Query('filter') filter?: 'all' | 'mentions' | 'comments',
    @Query('limit') limit?: number,
  ) {
    const items = await this.activityService.getActivityFeed(req.user.userId, {
      filter: filter || 'all',
      limit: limit ? parseInt(String(limit), 10) : 20,
    });
    return { items };
  }

  /**
   * 获取用户 Analytics
   */
  @Get('user-analytics')
  async getUserAnalytics(@Request() req: any) {
    const analytics = await this.activityService.getUserAnalytics(
      req.user.userId,
    );
    return analytics;
  }

  /**
   * 获取未读提及数量
   */
  @Get('unread-mentions')
  async getUnreadMentionCount(@Request() req: any) {
    const count = await this.activityService.getUnreadMentionCount(
      req.user.userId,
    );
    return { count };
  }

  /**
   * 标记提及为已读
   */
  @Post('mentions/:id/read')
  async markMentionAsRead(
    @Request() req: any,
    @Param('id', ParseUUIDPipe) id: string,
  ) {
    await this.activityService.markMentionAsRead(id, req.user.userId);
    return { success: true };
  }

  private async safeRemove(filePath: string) {
    try {
      await fs.promises.unlink(filePath);
    } catch {
      // ignore temp cleanup errors
    }
  }
}
