import { Dispatch, SetStateAction, useState } from "react";
import {
  Paper,
  Group,
  Text,
  Stack,
  TextInput,
  Badge,
  ScrollArea,
  Checkbox,
  Box,
  Button,
} from "@mantine/core";
import { useTranslation } from "react-i18next";
import { IconSearch } from "@tabler/icons-react";
import type { QuestionBrief } from "../types/exam";

type actionTypes = "add" | "remove";

interface QuestionAssignerProps {
  available: QuestionBrief[];
  assigned: QuestionBrief[];
  onChange: (assigned: QuestionBrief[]) => void;
  mode?: "manual" | "random";
  actions?: Dispatch<SetStateAction<actionTypes | undefined>>;
}

function QuestionList({
  items,
  selected,
  onToggle,
  search,
  onSearchChange,
  label,
}: {
  items: QuestionBrief[];
  selected: Set<string>;
  onToggle: (id: string) => void;
  search: string;
  onSearchChange: (v: string) => void;
  label: string;
}) {
  const { t, i18n } = useTranslation();
  const locale = i18n.language as "en" | "am";
  const placeholder = t("exam.assigner.search");
  return (
    <Box style={{ flex: 1, minWidth: 0 }}>
      <Text fz="xs" fw={600} c="dimmed" mb={4}>
        {label} ({items.length})
      </Text>
      <Paper withBorder radius="md">
        <Group p="sm" pb={0}>
          <TextInput
            placeholder={placeholder}
            leftSection={<IconSearch size={14} />}
            value={search}
            onChange={(e) => onSearchChange(e.currentTarget.value)}
            size="xs"
            style={{ flex: 1 }}
          />
        </Group>
        <ScrollArea h={280} p="sm" pt="xs">
          <Stack gap={4}>
            {items.length === 0 && (
              <Text fz="xs" c="dimmed" ta="center" py="xl">
                {t("exam.assigner.noQuestions")}
              </Text>
            )}
            {items.map((q) => (
              <Paper
                key={q.id}
                withBorder
                p="xs"
                radius="sm"
                style={{
                  cursor: "pointer",
                  borderColor: selected.has(q.id)
                    ? "var(--mantine-color-blue-5)"
                    : undefined,
                  background: selected.has(q.id)
                    ? "var(--mantine-color-blue-0)"
                    : undefined,
                }}
                onClick={() => onToggle(q.id)}
              >
                <Group gap="sm" wrap="nowrap">
                  <Checkbox
                    checked={selected.has(q.id)}
                    onChange={() => onToggle(q.id)}
                    size="xs"
                  />
                  <div style={{ flex: 1, minWidth: 0 }}>
                    <Text fz="xs" lineClamp={2}>
                      {q.title[locale]}
                    </Text>
                    <Group gap={4} mt={2}>
                      <Badge
                        size="xs"
                        variant="light"
                        color={q.form === "ESSAY" ? "blue" : "violet"}
                      >
                        {q.form}
                      </Badge>
                      <Badge size="xs" variant="light" color="gray">
                        {q.points} pts
                      </Badge>
                    </Group>
                  </div>
                </Group>
              </Paper>
            ))}
          </Stack>
        </ScrollArea>
      </Paper>
    </Box>
  );
}

export function QuestionAssigner({
  available,
  assigned,
  onChange,
  mode = "manual",
  actions,
}: QuestionAssignerProps) {
  const { t } = useTranslation();
  const [searchLeft, setSearchLeft] = useState("");
  const [searchRight, setSearchRight] = useState("");
  const [selectedLeft, setSelectedLeft] = useState<Set<string>>(new Set());
  const [selectedRight, setSelectedRight] = useState<Set<string>>(new Set());
  const assignedIds = new Set(assigned.map((q) => q.id));

  const filteredAvailable = available.filter(
    (q) =>
      !assignedIds.has(q.id) &&
      (q.title.en.toLowerCase().includes(searchLeft.toLowerCase()) ||
        q.title.am.includes(searchLeft)),
  );
  const filteredAssigned = assigned.filter(
    (q) =>
      q.title.en.toLowerCase().includes(searchRight.toLowerCase()) ||
      q.title.am.includes(searchRight),
  );

  const assignSelected = () => {
    const toAssign = available.filter((q) => selectedLeft.has(q.id));
    onChange([...assigned, ...toAssign]);
    actions?.("add");
    setSelectedLeft(new Set());
  };

  const removeSelected = () => {
    onChange(assigned.filter((q) => !selectedRight.has(q.id)));
    actions?.("remove");
    setSelectedRight(new Set());
  };

  return (
    <Stack gap="sm">
      {mode === "manual" && (
        <Text fz="sm" fw={500}>
          {t("exam.assigner.title")}
        </Text>
      )}
      {mode === "random" && (
        <Text fz="sm" fw={500}>
          {t("exam.assigner.assignedTitle")}
        </Text>
      )}
      <Group gap="sm" align="stretch" wrap="nowrap">
        {mode === "manual" && (
          <QuestionList
            items={filteredAvailable}
            selected={selectedLeft}
            onToggle={(id) => {
              const next = new Set(selectedLeft);
              if (next.has(id)) next.delete(id);
              else next.add(id);
              setSelectedLeft(next);
            }}
            search={searchLeft}
            onSearchChange={setSearchLeft}
            label={t("exam.assigner.available")}
          />
        )}
        <QuestionList
          items={filteredAssigned}
          selected={selectedRight}
          onToggle={(id) => {
            const next = new Set(selectedRight);
            if (next.has(id)) next.delete(id);
            else next.add(id);
            setSelectedRight(next);
          }}
          search={searchRight}
          onSearchChange={setSearchRight}
          label={t("exam.assigner.assigned")}
        />
      </Group>
      {mode === "manual" && (
        <Group gap="sm" justify="center">
          {selectedLeft.size > 0 && (
            <Button size="xs" variant="light" onClick={assignSelected}>
              {t("exam.assigner.assignSelected", { count: selectedLeft.size })}
            </Button>
          )}
          {selectedRight.size > 0 && (
            <Button
              size="xs"
              variant="light"
              color="red"
              onClick={removeSelected}
            >
              {t("exam.assigner.removeSelected", { count: selectedRight.size })}
            </Button>
          )}
        </Group>
      )}
      {mode === "random" && selectedRight.size > 0 && (
        <Group gap="sm" justify="center">
          <Button
            size="xs"
            variant="light"
            color="red"
            onClick={removeSelected}
          >
            {t("exam.assigner.removeSelected", { count: selectedRight.size })}
          </Button>
        </Group>
      )}
    </Stack>
  );
}
