import React, { FormEventHandler, useCallback, useEffect, useState } from 'react';
import FocusTrap from 'focus-trap-react';
import {
  Box,
  Text,
  Input,
  Button,
  Dialog,
  IconButton,
  Icon,
  Icons,
  Overlay,
  OverlayBackdrop,
  OverlayCenter,
  Header,
  config,
  color,
  Spinner,
} from 'folds';
import { Method } from 'matrix-js-sdk';
import { AsyncStatus, useAsyncCallback } from '../../hooks/useAsyncCallback';
import { ReportCategorySelect } from './ReportCategorySelect';
import { useMatrixClient } from '../../hooks/useMatrixClient';
import { stopPropagation } from '../../utils/keyboard';
import { useModalStyle } from '../../hooks/useModalStyle';

type ReportCategory = 'spam' | 'harassment' | 'inappropriate' | 'other';

const CATEGORY_LABELS: Record<ReportCategory, string> = {
  spam: 'Spam',
  harassment: 'Harassment',
  inappropriate: 'Inappropriate Content',
  other: 'Other',
};

type ReportUserModalProps = {
  userId: string;
  onClose: () => void;
};

export function ReportUserModal({ userId, onClose }: ReportUserModalProps) {
  const mx = useMatrixClient();
  const modalStyle = useModalStyle(420);
  const [category, setCategory] = useState<ReportCategory>('spam');

  const [reportState, submitReport] = useAsyncCallback(
    useCallback(
      async (reason: string) => {
        await mx.http.authedRequest(
          Method.Post,
          `/users/${encodeURIComponent(userId)}/report`,
          undefined,
          { reason },
        );
      },
      [mx, userId],
    ),
  );

  useEffect(() => {
    if (reportState.status === AsyncStatus.Success) {
      const timer = setTimeout(onClose, 1500);
      return () => clearTimeout(timer);
    }
    return undefined;
  }, [reportState.status, onClose]);

  const handleSubmit: FormEventHandler<HTMLFormElement> = (evt) => {
    evt.preventDefault();
    if (reportState.status === AsyncStatus.Loading || reportState.status === AsyncStatus.Success) {
      return;
    }
    const target = evt.target as HTMLFormElement;
    const reasonInput = target.elements.namedItem('reasonInput') as HTMLInputElement | null;
    const reasonText = reasonInput?.value.trim() ?? '';
    const fullReason = `[${CATEGORY_LABELS[category]}] ${reasonText}`;
    submitReport(fullReason);
  };

  const reportError =
    reportState.status === AsyncStatus.Error
      ? (reportState.error as { errcode?: string; httpStatus?: number })
      : undefined;
  const errcode = reportError?.errcode;
  const errorMsg =
    errcode === 'M_LIMIT_EXCEEDED'
      ? 'You are being rate limited. Please wait before reporting again.'
      : errcode === 'M_FORBIDDEN'
        ? 'You cannot report this user.'
        : errcode === 'M_UNRECOGNIZED' || reportError?.httpStatus === 404
          ? 'User reporting is not supported by your homeserver.'
          : 'Failed to submit report. Please try again.';

  return (
    <Overlay open backdrop={<OverlayBackdrop />}>
      <OverlayCenter>
        <FocusTrap
          focusTrapOptions={{
            initialFocus: false,
            onDeactivate: onClose,
            clickOutsideDeactivates: true,
            escapeDeactivates: stopPropagation,
          }}
        >
          <Dialog
            as="form"
            variant="Surface"
            role="dialog"
            aria-modal="true"
            aria-labelledby="report-user-dialog-title"
            onSubmit={handleSubmit}
            style={modalStyle}
          >
            <Header
              style={{
                padding: `0 ${config.space.S200} 0 ${config.space.S400}`,
                borderBottomWidth: config.borderWidth.B300,
              }}
              variant="Surface"
              size="500"
            >
              <Box grow="Yes">
                <Text id="report-user-dialog-title" size="H4">
                  Report User
                </Text>
              </Box>
              <IconButton size="300" onClick={onClose} radii="300" aria-label="Close">
                <Icon src={Icons.Cross} />
              </IconButton>
            </Header>

            <Box direction="Column" gap="400" style={{ padding: config.space.S400 }}>
              <Text priority="400">
                Report this user to your homeserver admins. Please describe the issue below.
              </Text>

              <Box direction="Column" gap="100">
                <Text as="label" htmlFor="report-user-category" size="L400">
                  Category
                </Text>
                <ReportCategorySelect
                  id="report-user-category"
                  value={category}
                  labels={CATEGORY_LABELS}
                  onChange={(v) => setCategory(v as ReportCategory)}
                />
              </Box>

              <Box direction="Column" gap="100">
                <Text as="label" htmlFor="report-user-reason-input" size="L400">
                  Reason
                </Text>
                <Input
                  id="report-user-reason-input"
                  name="reasonInput"
                  aria-label="Reason for report"
                  variant="Background"
                  required
                />
                {reportState.status === AsyncStatus.Error && (
                  <Text style={{ color: color.Critical.Main }} size="T300">
                    {errorMsg}
                  </Text>
                )}
                {reportState.status === AsyncStatus.Success && (
                  <Text style={{ color: color.Success.Main }} size="T300">
                    User has been reported to the server.
                  </Text>
                )}
              </Box>

              <Box gap="200" justifyContent="End">
                <Button
                  type="submit"
                  variant="Critical"
                  radii="300"
                  before={
                    reportState.status === AsyncStatus.Loading ? (
                      <Spinner fill="Solid" variant="Critical" size="200" />
                    ) : undefined
                  }
                  aria-disabled={
                    reportState.status === AsyncStatus.Loading ||
                    reportState.status === AsyncStatus.Success
                  }
                >
                  <Text size="B400">
                    {reportState.status === AsyncStatus.Loading ? 'Reporting...' : 'Report User'}
                  </Text>
                </Button>
              </Box>
            </Box>
          </Dialog>
        </FocusTrap>
      </OverlayCenter>
    </Overlay>
  );
}
