/**
 * Report Service
 * Handles user reports of inappropriate content and automatic content takedown.
 *
 * Features:
 * - Report submission with confidential reporter identity
 * - Auto-takedown when 3+ different users report the same content
 * - Content reset on takedown (nickname → "玩家+随机数", signature/description cleared)
 * - Admin review confirmation
 */

const AuditLogger = require('./auditLogger');

// ============================================================
// Configuration
// ============================================================
const AUTO_TAKEOWN_THRESHOLD = 3; // Number of reports to trigger auto-takedown

// Valid report reasons
const REPORT_REASONS = {
  POLITICS: 'politics',
  PORNOGRAPHY: 'pornography',
  GAMBLING: 'gambling',
  OTHER: 'other',
};

class ReportService {
  /**
   * @param {object} options
   * @param {import('./auditLogger')} [options.logger] - Audit logger instance
   * @param {import('./violationService')} [options.violationService] - Violation service instance
   */
  constructor(options = {}) {
    this.logger = options.logger || new AuditLogger();
    this.violationService = options.violationService || null;

    /**
     * In-memory report records.
     * Key: contentId, Value: { targetUserId, contentType, contentSummary, reports: [{reporterId, reason, timestamp}], status, createdAt }
     * @type {Map<string, object>}
     */
    this._reports = new Map();

    /**
     * User content storage (for content reset on takedown).
     * Key: userId, Value: { nickname, signature, description, avatarUrl }
     * @type {Map<string, object>}
     */
    this._userContent = new Map();
  }

  /**
   * Submit a report for inappropriate content.
   * @param {object} entry
   * @param {string} entry.contentId - Unique identifier for the reported content
   * @param {string} entry.targetUserId - User ID of the content author
   * @param {string} entry.contentType - Type of content ('chat', 'nickname', 'signature', 'description', 'avatar')
   * @param {string} entry.contentSummary - Desensitized content summary
   * @param {string} entry.reporterId - User ID of the reporter
   * @param {string} entry.reason - Report reason (politics/pornography/gambling/other)
   * @returns {{ success: boolean, reportCount: number, autoTakenDown: boolean }}
   */
  submitReport(entry) {
    const {
      contentId,
      targetUserId,
      contentType,
      contentSummary,
      reporterId,
      reason,
    } = entry;

    // Validate reason
    if (!Object.values(REPORT_REASONS).includes(reason)) {
      return { success: false, reportCount: 0, autoTakenDown: false };
    }

    // Get or create report record
    let record = this._reports.get(contentId);
    if (!record) {
      record = {
        contentId,
        targetUserId,
        contentType,
        contentSummary,
        reports: [],
        status: 'active', // active | taken_down | reviewed
        createdAt: Date.now(),
      };
      this._reports.set(contentId, record);
    }

    // Check if already reported by same user
    const alreadyReported = record.reports.some(
      (r) => r.reporterId === reporterId
    );
    if (alreadyReported) {
      return {
        success: false,
        reportCount: record.reports.length,
        autoTakenDown: false,
      };
    }

    // Add the report
    record.reports.push({
      reporterId,
      reason,
      timestamp: Date.now(),
    });

    // Log the report (reporter identity kept confidential)
    this.logger.logReport({
      reporterId,
      targetUserId,
      contentSummary,
      reason,
    });

    console.log(
      `[ReportService] Report submitted for content ${contentId} by user *** (${record.reports.length}/${AUTO_TAKEOWN_THRESHOLD})`
    );

    // Check for auto-takedown
    let autoTakenDown = false;
    if (
      record.reports.length >= AUTO_TAKEOWN_THRESHOLD &&
      record.status === 'active'
    ) {
      autoTakenDown = this._autoTakedown(contentId, record);
    }

    return {
      success: true,
      reportCount: record.reports.length,
      autoTakenDown,
    };
  }

  /**
   * Auto-takedown content when threshold is reached.
   * @param {string} contentId
   * @param {object} record
   * @returns {boolean}
   */
  _autoTakedown(contentId, record) {
    record.status = 'taken_down';
    record.takenDownAt = Date.now();

    console.log(
      `[ReportService] Auto-takedown triggered for content ${contentId} (${record.reports.length} reports)`
    );

    // Reset the user's content
    this._resetUserContent(record.targetUserId, record.contentType);

    // Record violation for the content author
    if (this.violationService) {
      this.violationService.recordViolation({
        userId: record.targetUserId,
        violationType: 'report_takedown',
        contentSummary: record.contentSummary,
        scene: this._contentTypeToScene(record.contentType),
      });
    }

    return true;
  }

  /**
   * Confirm a report as violation (admin action).
   * @param {string} contentId
   * @returns {{ success: boolean }}
   */
  confirmViolation(contentId) {
    const record = this._reports.get(contentId);
    if (!record) {
      return { success: false };
    }

    record.status = 'reviewed';
    record.reviewedAt = Date.now();

    // Reset the user's content
    this._resetUserContent(record.targetUserId, record.contentType);

    // Record violation for the content author
    if (this.violationService) {
      this.violationService.recordViolation({
        userId: record.targetUserId,
        violationType: 'admin_confirmed',
        contentSummary: record.contentSummary,
        scene: this._contentTypeToScene(record.contentType),
      });
    }

    console.log(
      `[ReportService] Admin confirmed violation for content ${contentId}`
    );

    return { success: true };
  }

  /**
   * Reset user content after takedown or deletion.
   * Nickname → "玩家" + random 4-digit number
   * Signature/description → cleared
   * @param {string} userId
   * @param {string} contentType
   */
  _resetUserContent(userId, contentType) {
    let userContent = this._userContent.get(userId);
    if (!userContent) {
      userContent = { nickname: '', signature: '', description: '', avatarUrl: '' };
      this._userContent.set(userId, userContent);
    }

    switch (contentType) {
      case 'nickname':
        userContent.nickname = `玩家${Math.floor(1000 + Math.random() * 9000)}`;
        break;
      case 'signature':
        userContent.signature = '';
        break;
      case 'description':
        userContent.description = '';
        break;
      case 'avatar':
        userContent.avatarUrl = '';
        break;
      case 'chat':
        // Chat messages are just hidden, no user content reset needed
        break;
    }

    console.log(
      `[ReportService] Content reset for user ${userId}, type: ${contentType}`
    );
  }

  /**
   * Convert content type to scene number.
   * @param {string} contentType
   * @returns {number}
   */
  _contentTypeToScene(contentType) {
    const map = {
      nickname: 1,
      chat: 2,
      signature: 3,
      description: 4,
      avatar: 5,
    };
    return map[contentType] || 0;
  }

  /**
   * Get report status for a content item.
   * @param {string} contentId
   * @returns {object|null}
   */
  getReportStatus(contentId) {
    const record = this._reports.get(contentId);
    if (!record) return null;

    return {
      contentId: record.contentId,
      contentType: record.contentType,
      reportCount: record.reports.length,
      status: record.status,
      // Do NOT expose reporter identities
    };
  }

  /**
   * Get all pending reports for admin review.
   * @returns {Array}
   */
  getPendingReports() {
    const pending = [];
    for (const record of this._reports.values()) {
      if (record.status === 'taken_down') {
        pending.push({
          contentId: record.contentId,
          targetUserId: record.targetUserId,
          contentType: record.contentType,
          contentSummary: record.contentSummary,
          reportCount: record.reports.length,
          reasons: [...new Set(record.reports.map((r) => r.reason))],
          takenDownAt: record.takenDownAt,
        });
      }
    }
    return pending;
  }
}

// Export report reasons for external use
ReportService.REPORT_REASONS = REPORT_REASONS;

module.exports = ReportService;