import { Injectable, Inject } from '@nestjs/common';
import {
  ClassificationRuleEntity,
  RuleConditions,
  FieldCondition,
  GroupCondition,
} from '../../domain/entities/classification-rule.entity';
import {
  CLASSIFICATION_RULE_REPOSITORY,
  ClassificationRuleRepository,
} from '../../domain/repositories/classification-rule.repository';
import {
  USER_QUERY_REPOSITORY,
  IUserQueryRepository,
  UserQueryItem,
} from '../../domain/repositories/user-query.repository';

/**
 * 规则评估结果
 */
export interface RuleEvaluationResult {
  ruleId: string;
  ruleName: string;
  matched: boolean;
  tagId?: string;
  tagCode?: string;
}

/**
 * 用户规则评估结果
 */
export interface UserRuleEvaluationResult {
  accountSequence: string;
  matchedRules: RuleEvaluationResult[];
  matchedTagIds: string[];
}

/**
 * 规则引擎服务
 * 负责评估用户分类规则
 */
@Injectable()
export class RuleEngineService {
  constructor(
    @Inject(CLASSIFICATION_RULE_REPOSITORY)
    private readonly ruleRepository: ClassificationRuleRepository,
    @Inject(USER_QUERY_REPOSITORY)
    private readonly userQueryRepository: IUserQueryRepository,
  ) {}

  /**
   * 评估单个用户是否匹配规则
   */
  evaluateUser(user: UserQueryItem, rule: ClassificationRuleEntity): boolean {
    return this.evaluateConditions(user, rule.conditions);
  }

  /**
   * 评估用户匹配的所有规则
   */
  async evaluateUserRules(
    accountSequence: string,
  ): Promise<UserRuleEvaluationResult> {
    const user =
      await this.userQueryRepository.findByAccountSequence(accountSequence);
    if (!user) {
      return {
        accountSequence,
        matchedRules: [],
        matchedTagIds: [],
      };
    }

    const linkedRules = await this.ruleRepository.findLinkedRules();
    const matchedRules: RuleEvaluationResult[] = [];
    const matchedTagIds: string[] = [];

    for (const { rule, tagId, tagCode } of linkedRules) {
      if (!rule.isEnabled) continue;

      const matched = this.evaluateUser(user, rule);
      matchedRules.push({
        ruleId: rule.id,
        ruleName: rule.name,
        matched,
        tagId,
        tagCode,
      });

      if (matched) {
        matchedTagIds.push(tagId);
      }
    }

    return {
      accountSequence,
      matchedRules,
      matchedTagIds,
    };
  }

  /**
   * 批量评估用户规则
   */
  async evaluateUsersRules(
    accountSequences: string[],
  ): Promise<Map<string, UserRuleEvaluationResult>> {
    const results = new Map<string, UserRuleEvaluationResult>();

    // 获取所有已关联标签的启用规则
    const linkedRules = await this.ruleRepository.findLinkedRules();
    const enabledRules = linkedRules.filter((r) => r.rule.isEnabled);

    for (const accountSequence of accountSequences) {
      const user =
        await this.userQueryRepository.findByAccountSequence(accountSequence);
      if (!user) {
        results.set(accountSequence, {
          accountSequence,
          matchedRules: [],
          matchedTagIds: [],
        });
        continue;
      }

      const matchedRules: RuleEvaluationResult[] = [];
      const matchedTagIds: string[] = [];

      for (const { rule, tagId, tagCode } of enabledRules) {
        const matched = this.evaluateUser(user, rule);
        matchedRules.push({
          ruleId: rule.id,
          ruleName: rule.name,
          matched,
          tagId,
          tagCode,
        });

        if (matched) {
          matchedTagIds.push(tagId);
        }
      }

      results.set(accountSequence, {
        accountSequence,
        matchedRules,
        matchedTagIds,
      });
    }

    return results;
  }

  /**
   * 查找匹配规则的所有用户
   * 返回 accountSequence 列表
   */
  async findMatchingUsers(
    rule: ClassificationRuleEntity,
    options?: { limit?: number; offset?: number },
  ): Promise<{ accountSequences: string[]; total: number }> {
    // 获取所有用户并评估
    // TODO: 优化为数据库层面的筛选
    const result = await this.userQueryRepository.findMany(
      {},
      { page: 1, pageSize: 10000 },
    );

    const matchingSequences: string[] = [];
    for (const user of result.items) {
      if (this.evaluateUser(user, rule)) {
        matchingSequences.push(user.accountSequence);
      }
    }

    const total = matchingSequences.length;
    const offset = options?.offset ?? 0;
    const limit = options?.limit ?? total;

    return {
      accountSequences: matchingSequences.slice(offset, offset + limit),
      total,
    };
  }

  /**
   * 预估规则匹配用户数
   */
  async estimateMatchingUsers(rule: ClassificationRuleEntity): Promise<number> {
    const { total } = await this.findMatchingUsers(rule);
    return total;
  }

  /**
   * 评估条件组
   */
  private evaluateConditions(
    user: UserQueryItem,
    conditions: RuleConditions,
  ): boolean {
    return this.evaluateGroup(user, conditions);
  }

  /**
   * 评估条件组 (AND/OR)
   */
  private evaluateGroup(user: UserQueryItem, group: GroupCondition): boolean {
    if (group.type === 'AND') {
      return group.rules.every((rule) => {
        if ('type' in rule && ['AND', 'OR'].includes(rule.type as string)) {
          return this.evaluateGroup(user, rule as GroupCondition);
        }
        return this.evaluateFieldCondition(user, rule as FieldCondition);
      });
    } else {
      return group.rules.some((rule) => {
        if ('type' in rule && ['AND', 'OR'].includes(rule.type as string)) {
          return this.evaluateGroup(user, rule as GroupCondition);
        }
        return this.evaluateFieldCondition(user, rule as FieldCondition);
      });
    }
  }

  /**
   * 评估字段条件
   */
  private evaluateFieldCondition(
    user: UserQueryItem,
    condition: FieldCondition,
  ): boolean {
    const value = this.getFieldValue(user, condition.field);
    const compareValue = condition.value;

    switch (condition.operator) {
      case 'eq':
        return value === compareValue;

      case 'neq':
        return value !== compareValue;

      case 'gt':
        return typeof value === 'number' && value > Number(compareValue);

      case 'gte':
        return typeof value === 'number' && value >= Number(compareValue);

      case 'lt':
        return typeof value === 'number' && value < Number(compareValue);

      case 'lte':
        return typeof value === 'number' && value <= Number(compareValue);

      case 'within_days': {
        // 在 N 天内
        if (!(value instanceof Date)) return false;
        const daysAgo = new Date();
        daysAgo.setDate(daysAgo.getDate() - Number(compareValue));
        return value >= daysAgo;
      }

      case 'before_days': {
        // N 天前
        if (!(value instanceof Date)) return false;
        const daysAgo = new Date();
        daysAgo.setDate(daysAgo.getDate() - Number(compareValue));
        return value < daysAgo;
      }

      case 'in':
        if (Array.isArray(compareValue)) {
          return compareValue.includes(String(value));
        }
        return false;

      case 'not_in':
        if (Array.isArray(compareValue)) {
          return !compareValue.includes(String(value));
        }
        return true;

      default:
        return false;
    }
  }

  /**
   * 获取用户字段值
   */
  private getFieldValue(
    user: UserQueryItem,
    field: string,
  ): number | string | Date | null {
    switch (field) {
      case 'registeredAt':
        return user.registeredAt;
      case 'personalAdoptionCount':
        return user.personalAdoptionCount;
      case 'teamAdoptionCount':
        return user.teamAdoptionCount;
      case 'teamAddressCount':
        return user.teamAddressCount;
      case 'provinceAdoptionCount':
        return user.provinceAdoptionCount;
      case 'cityAdoptionCount':
        return user.cityAdoptionCount;
      case 'kycStatus':
        return user.kycStatus;
      case 'lastActiveAt':
        return user.lastActiveAt;
      case 'status':
        return user.status;
      default:
        return null;
    }
  }
}
