import React, { useCallback } from 'react';
import { Box, color, Spinner, Switch, Text } from 'folds';
import { useTranslation } from 'react-i18next';
import { MatrixError } from 'matrix-js-sdk';
import type { StateEvents } from 'matrix-js-sdk';
import { SettingTile } from '../../../components/setting-tile';
import { useRoom } from '../../../hooks/useRoom';
import { AsyncStatus, useAsyncCallback } from '../../../hooks/useAsyncCallback';
import { StateEvent } from '../../../../types/matrix/room';
import { useMatrixClient } from '../../../hooks/useMatrixClient';
import { useStateEvent } from '../../../hooks/useStateEvent';
import { RoomPermissionsAPI } from '../../../hooks/useRoomPermissions';

type RoomVoiceMessagesProps = {
  permissions: RoomPermissionsAPI;
};
// Per-room "allow voice messages" toggle. Writes the `in.vojo.room.voice_messages`
// state event. In a 1:1 both parties are PL 100 (TrustedPrivateChat) so either
// can flip it; in a group it requires `state_default` (admin). Soft, client-side,
// Vojo↔Vojo. See docs/plans/voice_messages.md §4.
export function RoomVoiceMessages({ permissions }: RoomVoiceMessagesProps) {
  const { t } = useTranslation();
  const mx = useMatrixClient();
  const room = useRoom();

  const canEdit = permissions.stateEvent(StateEvent.VoiceMessages, mx.getSafeUserId());
  const content = useStateEvent(room, StateEvent.VoiceMessages)?.getContent<{
    enabled?: boolean;
    disabled_by?: string;
  }>();
  // Default-on: absent OR enabled !== false ⇒ voice allowed.
  const allowed = content?.enabled !== false;

  const [setState, setAllowed] = useAsyncCallback(
    useCallback(
      async (nextAllowed: boolean) => {
        // Only stamp disabled_by when actually disabling — on re-enable it would
        // misleadingly name the re-enabler. The gate reads it only when
        // enabled === false anyway. See review notes in docs/plans/voice_messages.md.
        await mx.sendStateEvent(room.roomId, StateEvent.VoiceMessages as keyof StateEvents, {
          enabled: nextAllowed,
          ...(nextAllowed ? {} : { disabled_by: mx.getSafeUserId() }),
        });
      },
      [mx, room.roomId]
    )
  );

  const loading = setState.status === AsyncStatus.Loading;

  return (
    <SettingTile
      title={t('RoomSettings.voice_messages')}
      description={t('RoomSettings.voice_messages_desc')}
      after={
        <Box gap="200" alignItems="Center">
          {loading && <Spinner variant="Secondary" />}
          <Switch value={allowed} onChange={setAllowed} disabled={!canEdit || loading} />
        </Box>
      }
    >
      {setState.status === AsyncStatus.Error && (
        <Text style={{ color: color.Critical.Main }} size="T200">
          {(setState.error as MatrixError).message}
        </Text>
      )}
    </SettingTile>
  );
}
