import React, { useEffect, useState } from 'react';
import FocusTrap from 'focus-trap-react';
import {
  Avatar,
  Box,
  Button,
  Dialog,
  Header,
  Icon,
  IconButton,
  Icons,
  Overlay,
  OverlayBackdrop,
  OverlayCenter,
  Spinner,
  Switch,
  Text,
  color,
  config,
  toRem,
} from 'folds';
import { useTranslation } from 'react-i18next';
import { MatrixError } from 'matrix-js-sdk';
import { useMatrixClient } from '../../hooks/useMatrixClient';
import { useMediaAuthentication } from '../../hooks/useMediaAuthentication';
import { useAlive } from '../../hooks/useAlive';
import { UserAvatar } from '../../components/user-avatar';
import { nameInitials } from '../../utils/common';
import { getMxIdLocalPart, getMxIdServer, mxcUrlToHttp } from '../../utils/matrix';
import { stopPropagation } from '../../utils/keyboard';
import { ErrorCode } from '../../cs-errorcode';
import type { PendingDirect } from './useRoomSearch';

type StartDirectDialogProps = {
  target: PendingDirect;
  // True while `confirmDirect` is round-tripping `createRoom`.
  creating: boolean;
  // Already-localized DM-create failure, or undefined.
  errorText?: string;
  onConfirm: (encrypt: boolean) => void;
  onCancel: () => void;
};

// Small centered confirm step between tapping a person in search and
// actually opening/creating the DM. Shows who you're about to message
// (avatar + name + `@user:server`, with a cross-server note) and the
// per-chat E2EE choice. Dawn/Fleet `Dialog` surface, like the app's
// other prompts.
export function StartDirectDialog({
  target,
  creating,
  errorText,
  onConfirm,
  onCancel,
}: StartDirectDialogProps) {
  const { t } = useTranslation();
  const mx = useMatrixClient();
  const useAuthentication = useMediaAuthentication();
  const alive = useAlive();

  const [encrypt, setEncrypt] = useState(false);
  // Seed from whatever the clicked row knew, then refine with a fresh
  // profile lookup so a cross-server avatar/name always renders (the
  // homeserver proxies the remote `GET /profile` over federation).
  const [displayName, setDisplayName] = useState(target.displayName);
  const [avatarUrl, setAvatarUrl] = useState(target.avatarUrl);
  // Whether the homeserver could confirm this user exists. A (federated,
  // best-effort) profile lookup is the only existence signal Matrix has:
  //   found     — the server returned a profile → the user exists.
  //   notfound  — 404 → no such user on that server.
  //   error     — unreachable / federation off / timeout → can't tell.
  const [lookup, setLookup] = useState<'checking' | 'found' | 'notfound' | 'error'>('checking');

  useEffect(() => {
    setLookup('checking');
    mx.getProfileInfo(target.userId)
      .then((profile) => {
        if (!alive()) return;
        if (profile.displayname) setDisplayName(profile.displayname);
        if (profile.avatar_url) setAvatarUrl(profile.avatar_url);
        setLookup('found');
      })
      .catch((err: unknown) => {
        if (!alive()) return;
        if (err instanceof MatrixError && err.errcode === ErrorCode.M_NOT_FOUND) {
          setLookup('notfound');
        } else {
          setLookup('error');
        }
      });
  }, [mx, alive, target.userId]);

  // Only a clean 404 blocks the create (no such account → no ghost room).
  // `error` (server unreachable / couldn't verify) stays allowed — we got
  // here from an actionable card, so the account may well exist.
  const blocked = lookup === 'notfound';

  const username = getMxIdLocalPart(target.userId) ?? target.userId;
  const server = getMxIdServer(target.userId);
  const myServer = getMxIdServer(mx.getSafeUserId());
  const remote = !!server && !!myServer && server !== myServer;
  const name = displayName || username;
  const avatarSrc = avatarUrl
    ? mxcUrlToHttp(mx, avatarUrl, useAuthentication, 96, 96, 'crop') ?? undefined
    : undefined;

  return (
    <Overlay open backdrop={<OverlayBackdrop />}>
      <OverlayCenter>
        <FocusTrap
          focusTrapOptions={{
            initialFocus: false,
            onDeactivate: onCancel,
            clickOutsideDeactivates: true,
            allowOutsideClick: true,
            escapeDeactivates: stopPropagation,
          }}
        >
          <Dialog variant="Surface" style={{ width: toRem(340), maxWidth: '90vw' }}>
            <Header
              style={{
                padding: `0 ${config.space.S200} 0 ${config.space.S400}`,
                borderBottomWidth: config.borderWidth.B300,
              }}
              variant="Surface"
              size="500"
            >
              <Box grow="Yes">
                <Text size="H5">{t('Search.start_dm_title')}</Text>
              </Box>
              <IconButton size="300" radii="300" onClick={onCancel} aria-label={t('Search.clear')}>
                <Icon src={Icons.Cross} />
              </IconButton>
            </Header>

            {/* Identity preview */}
            <Box
              direction="Column"
              alignItems="Center"
              gap="200"
              style={{ padding: `${config.space.S500} ${config.space.S400} ${config.space.S200}` }}
            >
              <Avatar size="500" radii="400">
                <UserAvatar
                  userId={target.userId}
                  src={avatarSrc}
                  alt={name}
                  renderFallback={() => (
                    <Text as="span" size="H3">
                      {nameInitials(name)}
                    </Text>
                  )}
                />
              </Avatar>
              <Box direction="Column" alignItems="Center" gap="100" style={{ minWidth: 0 }}>
                <Text size="H6" align="Center" truncate style={{ maxWidth: toRem(290) }}>
                  {name}
                </Text>
                <Text
                  size="T200"
                  priority="300"
                  align="Center"
                  truncate
                  style={{ maxWidth: toRem(290), fontFamily: 'var(--font-mono)' }}
                >
                  {target.userId}
                </Text>
                {/* Existence / reachability status — the honest answer to
                    "is there really such a user". */}
                <Box alignItems="Center" gap="100" style={{ marginTop: toRem(2) }}>
                  {lookup === 'checking' && (
                    <>
                      <Spinner size="100" variant="Secondary" />
                      <Text size="T200" priority="300">
                        {t('Search.checking')}
                      </Text>
                    </>
                  )}
                  {lookup === 'found' && (
                    <>
                      <Icon size="50" src={Icons.Check} style={{ color: color.Success.Main }} />
                      <Text size="T200" style={{ color: color.Success.Main }}>
                        {remote ? t('Search.found_on_server', { server }) : t('Search.user_found')}
                      </Text>
                    </>
                  )}
                  {lookup === 'notfound' && (
                    <>
                      <Icon size="50" src={Icons.Warning} style={{ color: color.Warning.Main }} />
                      <Text size="T200" style={{ color: color.Warning.Main }}>
                        {t('Search.user_not_found', { server })}
                      </Text>
                    </>
                  )}
                  {lookup === 'error' && (
                    <>
                      <Icon size="50" src={Icons.Warning} style={{ color: color.Warning.Main }} />
                      <Text size="T200" style={{ color: color.Warning.Main }}>
                        {t('Search.user_unreachable', { server })}
                      </Text>
                    </>
                  )}
                </Box>
              </Box>
            </Box>

            {/* Options + action */}
            <Box direction="Column" gap="300" style={{ padding: config.space.S400 }}>
              <Box
                as="label"
                alignItems="Center"
                gap="200"
                style={{
                  padding: `${toRem(10)} ${toRem(12)}`,
                  borderRadius: toRem(12),
                  backgroundColor: color.Background.Container,
                  cursor: 'pointer',
                }}
              >
                <Icon
                  size="100"
                  src={Icons.ShieldUser}
                  style={{ color: encrypt ? color.Success.Main : undefined }}
                />
                <Box grow="Yes">
                  <Text size="T300">{t('Search.encrypt_label')}</Text>
                </Box>
                <Switch variant="Success" value={encrypt} onChange={setEncrypt} />
              </Box>

              {errorText && (
                <Box alignItems="Center" gap="200" style={{ color: color.Critical.Main }}>
                  <Icon size="100" src={Icons.Warning} />
                  <Text size="T200" style={{ color: color.Critical.Main }}>
                    {errorText}
                  </Text>
                </Box>
              )}

              <Button
                variant="Primary"
                radii="400"
                onClick={() => onConfirm(encrypt)}
                disabled={creating || blocked}
                before={
                  creating ? <Spinner variant="Primary" fill="Solid" size="200" /> : undefined
                }
              >
                <Text size="B400">{t('Search.start_dm_action')}</Text>
              </Button>
            </Box>
          </Dialog>
        </FocusTrap>
      </OverlayCenter>
    </Overlay>
  );
}
