import type { ApiMessage } from '../../api/types';
import type { MessageFilterRule } from '../../global/types/sharedState';

const compiledRegexCache = new Map<string, RegExp | null>();

function getCompiledRegex(pattern: string, caseInsensitive?: boolean): RegExp | null {
  const key = `${caseInsensitive ? 'i' : ''}:${pattern}`;
  if (!compiledRegexCache.has(key)) {
    try {
      compiledRegexCache.set(key, new RegExp(pattern, caseInsensitive ? 'i' : ''));
    } catch {
      compiledRegexCache.set(key, null);
    }
  }
  return compiledRegexCache.get(key) ?? null;
}

function getMessageMediaTypes(message: ApiMessage): string[] {
  const { content } = message;
  return [
    content.text && 'text',
    content.photo && 'photo',
    content.video && 'video',
    content.document && 'document',
    content.sticker && 'sticker',
    content.voice && 'voice',
    content.audio && 'audio',
    content.webPage && 'webPage',
    content.pollId && 'poll',
    content.storyData && 'story',
  ].filter(Boolean) as string[];
}

export function shouldHideMessageByRules(
  message: ApiMessage,
  rules: MessageFilterRule[] = [],
): boolean {
  if (!rules.length) return false;

  // Never filter action/service messages
  if (message.content.action) return false;

  const text = message.content.text?.text ?? '';
  const mediaTypes = getMessageMediaTypes(message);

  return rules.some((rule) => {
    if (!rule.enabled) return false;

    if (rule.chatIds?.length && !rule.chatIds.includes(message.chatId)) return false;
    if (rule.senderIds?.length && (!message.senderId || !rule.senderIds.includes(message.senderId))) return false;
    if (rule.mediaTypes?.length && !rule.mediaTypes.some((t) => mediaTypes.includes(t))) return false;

    let matched = false;

    if (rule.keyword) {
      matched = rule.caseInsensitive
        ? text.toLowerCase().includes(rule.keyword.toLowerCase())
        : text.includes(rule.keyword);
    } else if (rule.regex) {
      const re = getCompiledRegex(rule.regex, rule.caseInsensitive);
      matched = re ? re.test(text) : false;
    } else if (rule.mediaTypes?.length) {
      matched = true;
    }

    return rule.reversed ? !matched : matched;
  });
}
