import type { ParsedEvent } from '../models/api.types';
import { unwrapJsonPayload } from '../../shared/utils/json.util';

import { keyNameModifiersPayloadToSvgIds } from './keyboard-key-name-map';
import { type KeyboardVkScheme, vkToKeyboardSvgKeyId } from './vk-to-keyboard-svg-id';

export function isKeyboardTelemetryEvent(event: ParsedEvent): boolean {
  const t = (event.event_type ?? '').toLowerCase();
  return t.includes('keyboard') || t.includes('key');
}

export function parseKeyboardVirtualKey(data: unknown): number | null {
  if (data == null) {
    return null;
  }
  if (Array.isArray(data)) {
    if (data.length >= 1) {
      const v = data[0];
      if (typeof v === 'number' && Number.isFinite(v)) {
        return v;
      }
      if (typeof v === 'string') {
        const n = parseInt(v, 10);
        return Number.isFinite(n) ? n : null;
      }
    }
    return null;
  }
  if (typeof data === 'object') {
    const o = data as Record<string, unknown>;
    for (const key of ['vk', 'virtualKey', 'VirtualKey', 'keyCode', 'KeyCode', 'wParam']) {
      const v = o[key];
      if (typeof v === 'number' && Number.isFinite(v)) {
        return v;
      }
      if (typeof v === 'string') {
        const n = parseInt(v, 10);
        if (Number.isFinite(n)) {
          return n;
        }
      }
    }
  }
  return null;
}

const MAC_VK_SCHEME_HINTS = new Set([
  'carbon',
  'darwin',
  'mac',
  'mac_os',
  'macos',
  'macos_vk',
  'osx',
]);

const WINDOWS_VK_SCHEME_HINTS = new Set(['win', 'win32', 'win64', 'windows', 'windows_vk']);

/**
 * Определяет семейство кодов клавиш по полям payload (агент должен выставлять при записи).
 * По умолчанию — Windows VK, как раньше.
 */
export function parseKeyboardVkScheme(data: unknown): KeyboardVkScheme {
  const raw = unwrapJsonPayload(data);
  if (raw != null && typeof raw === 'object' && !Array.isArray(raw)) {
    const o = raw as Record<string, unknown>;
    const keys = ['vk_scheme', 'vkScheme', 'platform', 'os', 'os_type', 'OS'] as const;
    for (const k of keys) {
      const v = o[k];
      if (typeof v === 'string') {
        const s = v.trim().toLowerCase();
        if (MAC_VK_SCHEME_HINTS.has(s)) {
          return 'macos';
        }
        if (WINDOWS_VK_SCHEME_HINTS.has(s)) {
          return 'windows';
        }
      }
    }
  }
  return 'windows';
}

export function eventPayloadJson(data: unknown): string {
  try {
    return JSON.stringify(data, null, 2);
  } catch {
    return String(data);
  }
}

export function parseKeyboardAction(data: unknown): 'press' | 'release' | null {
  const raw = unwrapJsonPayload(data);
  if (raw != null && typeof raw === 'object' && !Array.isArray(raw)) {
    const o = raw as Record<string, unknown>;
    const action = o['action'];
    if (typeof action === 'string') {
      const normalized = action.toLowerCase();
      if (normalized === 'press' || normalized === 'down' || normalized === 'key_down') {
        return 'press';
      }
      if (normalized === 'release' || normalized === 'up' || normalized === 'key_up') {
        return 'release';
      }
    }
    if (typeof o['is_down'] === 'boolean') {
      return o['is_down'] ? 'press' : 'release';
    }
  }
  return null;
}

export function parseKeyboardHighlightKeyIds(data: unknown): string[] {
  const raw = unwrapJsonPayload(data);
  if (raw != null && typeof raw === 'object' && !Array.isArray(raw)) {
    const o = raw as Record<string, unknown>;
    if (typeof o['key_name'] === 'string' || typeof o['modifiers'] === 'string') {
      const fromNames = keyNameModifiersPayloadToSvgIds(o);
      if (fromNames.length > 0) {
        return fromNames;
      }
    }
  }
  const vk = parseKeyboardVirtualKey(raw);
  if (vk != null) {
    const scheme = parseKeyboardVkScheme(raw);
    const id = vkToKeyboardSvgKeyId(vk, scheme);
    return id ? [id] : [];
  }
  return [];
}
