import { useCallback } from 'react';
import { ICreateRoomStateEvent, Preset, Visibility } from 'matrix-js-sdk';
import { useMatrixClient } from '../../hooks/useMatrixClient';
import { addRoomIdToMDirect, getDMRoomFor } from '../../utils/matrix';
import { createRoomEncryptionState } from '../../components/create-room';

export type CreateDirectOptions = {
  // End-to-end encrypt the freshly created room. Ignored when an
  // existing DM is reused. Defaults to `false` to match the historical
  // `CreateChat` toggle default.
  encrypt?: boolean;
};

// Single source of truth for "open or create a 1:1 DM with `userId`".
// Returns the existing DM's roomId when one is already tracked in
// `m.direct` (dedup via `getDMRoomFor`); otherwise creates a fresh
// `is_direct` room, records it in `m.direct`, and returns the new
// roomId. Shared by the legacy `CreateChat` form and the unified
// search People section so both reach a DM through the exact same path.
export function useCreateDirect(): (userId: string, opts?: CreateDirectOptions) => Promise<string> {
  const mx = useMatrixClient();

  return useCallback(
    async (userId, opts) => {
      const existing = getDMRoomFor(mx, userId);
      if (existing) return existing.roomId;

      const initialState: ICreateRoomStateEvent[] = [];
      if (opts?.encrypt) initialState.push(createRoomEncryptionState());

      const result = await mx.createRoom({
        is_direct: true,
        invite: [userId],
        visibility: Visibility.Private,
        preset: Preset.TrustedPrivateChat,
        initial_state: initialState,
        // No power_level override: TrustedPrivateChat already gives both parties
        // PL 100, so either can write the voice-messages state event. (A custom
        // `events` override would shallow-REPLACE Synapse's default events map
        // and weaken the room's state-event protections.) See voice_messages.md §4.
      });

      addRoomIdToMDirect(mx, result.room_id, userId);

      return result.room_id;
    },
    [mx]
  );
}
