import { MatrixClient, MatrixEvent, Room } from 'matrix-js-sdk';
import { SoundboardPack } from './SoundboardPack';
import {
  LegacySoundboardContent,
  SoundboardClips,
  SoundboardContent,
  SoundboardRoomsContent,
} from './types';
import { StateEvent } from '../../../types/matrix/room';
import { AccountDataEvent } from '../../../types/matrix/accountData';
import { getAccountData, getStateEvent, getStateEvents } from '../../utils/room';

/** Normalize a display name into a pack shortcode key (parallels emoji shortcodes). */
export function slugifyClipName(name: string): string {
  const s = name
    .trim()
    .toLowerCase()
    .replace(/\s+/g, '_')
    .replace(/[^a-z0-9_-]/g, '');
  return s || 'clip';
}

/** Pick a shortcode not already present in `taken`, suffixing on collision. */
export function uniqueShortcode(base: string, taken: Set<string>): string {
  const code = slugifyClipName(base);
  if (!taken.has(code)) return code;
  let i = 2;
  while (taken.has(`${code}-${i}`)) i += 1;
  return `${code}-${i}`;
}

export function makeSoundboardPacks(packEvents: MatrixEvent[]): SoundboardPack[] {
  return packEvents.reduce<SoundboardPack[]>((packs, packEvent) => {
    const packId = packEvent.getId();
    if (!packId) return packs;
    packs.push(SoundboardPack.fromMatrixEvent(packId, packEvent));
    return packs;
  }, []);
}

export function getRoomSoundboardPack(room: Room, stateKey: string): SoundboardPack | undefined {
  const packEvent = getStateEvent(room, StateEvent.LotusSoundboardRoom, stateKey);
  if (!packEvent) return undefined;
  const packId = packEvent.getId();
  if (!packId) return undefined;
  return SoundboardPack.fromMatrixEvent(packId, packEvent);
}

export function getRoomSoundboardPacks(room: Room): SoundboardPack[] {
  return makeSoundboardPacks(getStateEvents(room, StateEvent.LotusSoundboardRoom));
}

export function getGlobalSoundboardPacks(mx: MatrixClient): SoundboardPack[] {
  const content = getAccountData(mx, AccountDataEvent.LotusSoundboardRooms)?.getContent() as
    | SoundboardRoomsContent
    | undefined;
  const roomIdToPackInfo = content?.rooms;
  if (typeof roomIdToPackInfo !== 'object' || !roomIdToPackInfo) return [];

  return Object.keys(roomIdToPackInfo).flatMap((roomId) => {
    if (typeof roomIdToPackInfo[roomId] !== 'object') return [];
    const room = mx.getRoom(roomId);
    if (!room) return [];
    const stateKeys = roomIdToPackInfo[roomId];
    const globalEvents = getStateEvents(room, StateEvent.LotusSoundboardRoom).filter((mE) => {
      const stateKey = mE.getStateKey();
      return typeof stateKey === 'string' ? !!stateKeys[stateKey] : false;
    });
    return makeSoundboardPacks(globalEvents);
  });
}

/**
 * Convert a personal soundboard account-data content to the v2 pack shape,
 * migrating the v1 flat-list form (`{clips: [{id,name,url}]}`) on the fly.
 */
export function migrateUserSoundboardContent(raw: unknown): SoundboardContent {
  if (typeof raw !== 'object' || raw === null) return {};
  const legacy = raw as LegacySoundboardContent;
  if (!Array.isArray(legacy.clips)) return raw as SoundboardContent; // already v2 (or empty)

  const clips: SoundboardClips = {};
  const taken = new Set<string>();
  legacy.clips.forEach((c) => {
    if (!c || typeof c.url !== 'string') return;
    const shortcode = uniqueShortcode(c.name || 'clip', taken);
    taken.add(shortcode);
    clips[shortcode] = {
      url: c.url,
      body: c.name,
      info: { mimetype: c.mimetype, size: c.size },
    };
  });
  return { pack: { display_name: 'My Soundboard' }, clips };
}

export function getUserSoundboardPack(mx: MatrixClient): SoundboardPack | undefined {
  const packEvent = getAccountData(mx, AccountDataEvent.LotusSoundboard);
  const userId = mx.getUserId();
  if (!packEvent || !userId) return undefined;
  const content = migrateUserSoundboardContent(packEvent.getContent());
  return new SoundboardPack(userId, content, undefined);
}
