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

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

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

type ReportRoomModalProps = {
  roomId: string;
  onClose: () => void;
};

export function ReportRoomModal({ roomId, onClose }: ReportRoomModalProps) {
  const mx = useMatrixClient();
  const [category, setCategory] = useState<ReportCategory>('spam');

  const [reportState, submitReport] = useAsyncCallback(
    useCallback(
      async (reason: string) => {
        await mx.reportRoom(roomId, reason);
      },
      [mx, roomId],
    ),
  );

  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 errcode =
    reportState.status === AsyncStatus.Error
      ? (reportState.error as { errcode?: string })?.errcode
      : undefined;
  const errorMsg =
    errcode === 'M_LIMIT_EXCEEDED'
      ? 'You are being rate limited. Please wait before reporting again.'
      : errcode === 'M_FORBIDDEN'
        ? 'You cannot report this room.'
        : 'Failed to submit report. Please try again.';

  return (
    <Overlay open backdrop={<OverlayBackdrop />}>
      <OverlayCenter>
        <FocusTrap
          focusTrapOptions={{
            initialFocus: false,
            onDeactivate: onClose,
            clickOutsideDeactivates: true,
            escapeDeactivates: stopPropagation,
          }}
        >
          <Box
            as="form"
            role="dialog"
            aria-modal="true"
            aria-labelledby="report-room-dialog-title"
            onSubmit={handleSubmit}
            direction="Column"
            style={{
              background: color.Surface.Container,
              borderRadius: config.radii.R400,
              boxShadow: color.Other.Shadow,
              width: '100%',
              maxWidth: 420,
              overflow: 'hidden',
            }}
          >
            <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-room-dialog-title" size="H4">
                  Report Room
                </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 room to your homeserver admins. Please describe the issue below.
              </Text>

              <Box direction="Column" gap="100">
                <Text as="label" htmlFor="report-category" size="L400">
                  Category
                </Text>
                <Box
                  as="select"
                  id="report-category"
                  aria-label="Report category"
                  value={category}
                  onChange={(e: React.ChangeEvent<HTMLSelectElement>) =>
                    setCategory(e.target.value as ReportCategory)
                  }
                  style={{
                    padding: `${config.space.S200} ${config.space.S300}`,
                    borderRadius: config.radii.R300,
                    border: `1px solid ${color.Surface.ContainerLine}`,
                    background: color.Surface.Container,
                    color: color.Surface.OnContainer,
                    fontSize: 'inherit',
                    fontFamily: 'inherit',
                    width: '100%',
                  }}
                >
                  {(Object.keys(CATEGORY_LABELS) as ReportCategory[]).map((key) => (
                    <option key={key} value={key}>
                      {CATEGORY_LABELS[key]}
                    </option>
                  ))}
                </Box>
              </Box>

              <Box direction="Column" gap="100">
                <Text as="label" htmlFor="report-reason-input" size="L400">
                  Reason
                </Text>
                <Input
                  id="report-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">
                    Room has been reported to the server.
                  </Text>
                )}
              </Box>

              <Box gap="200" justifyContent="End">
                <Button type="button" variant="Secondary" fill="None" radii="300" onClick={onClose}>
                  <Text size="B400">Cancel</Text>
                </Button>
                <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 Room'}
                  </Text>
                </Button>
              </Box>
            </Box>
          </Box>
        </FocusTrap>
      </OverlayCenter>
    </Overlay>
  );
}
