import {
  Alert,
  Badge,
  Button,
  Card,
  Group,
  Modal,
  NumberInput,
  Select,
  Stack,
  Table,
  Text,
  TextInput,
} from "@mantine/core";
import { IconAlertTriangle, IconPlus } from "@tabler/icons-react";
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
import { useState } from "react";
import { useNavigate } from "react-router-dom";
import { useTranslation } from "react-i18next";

import { Can } from "@/auth/Can";
import { HR_PERMS } from "@/auth/permissions";
import { apiErrorMessage } from "@/auth/http";
import { PageHeader } from "@/shared/components/PageHeader";
import { BilingualTextInput } from "@/shared/components/BilingualTextInput";
import { EthiopianDateInput } from "@/shared/components/EthiopianDateInput";
import { localized } from "@/shared/lib/localizedName";
import { createOpening, listOpenings, publishOpening } from "./api";
import { OpeningBadge } from "./components/StageBadge";

export function OpeningsPage() {
  const queryClient = useQueryClient();
  const navigate = useNavigate();
  const { i18n } = useTranslation();
  const [creating, setCreating] = useState(false);
  const [error, setError] = useState<string | null>(null);

  const openings = useQuery({
    queryKey: ["job-openings"],
    queryFn: () => listOpenings({ limit: 50 }),
  });

  const publish = useMutation({
    mutationFn: (payload: { id: string; closesOn?: string }) =>
      publishOpening(payload.id, payload.closesOn),
    onSuccess: () => queryClient.invalidateQueries({ queryKey: ["job-openings"] }),
    onError: (err) => setError(apiErrorMessage(err)),
  });

  const items = openings.data?.items ?? [];

  return (
    <>
      <PageHeader
        title="Recruitment"
        description="Vacancies and where each one has got to"
        actions={
          <Can permission={HR_PERMS.recruitment.manageJobOpening}>
            <Button leftSection={<IconPlus size={16} />} onClick={() => setCreating(true)}>
              New vacancy
            </Button>
          </Can>
        }
      />

      {error && (
        <Alert
          color="red"
          mb="md"
          withCloseButton
          onClose={() => setError(null)}
          icon={<IconAlertTriangle size={18} />}
        >
          {error}
        </Alert>
      )}

      <Card withBorder radius="md" p={0}>
        <Table.ScrollContainer minWidth={880}>
          <Table striped highlightOnHover verticalSpacing="sm">
            <Table.Thead>
              <Table.Tr>
                <Table.Th>Vacancy</Table.Th>
                <Table.Th>Status</Table.Th>
                <Table.Th>Seats</Table.Th>
                <Table.Th>Salary range</Table.Th>
                <Table.Th>Closes</Table.Th>
                <Table.Th />
              </Table.Tr>
            </Table.Thead>
            <Table.Tbody>
              {items.map((opening) => (
                <Table.Tr
                  key={opening.id}
                  style={{ cursor: "pointer" }}
                  onClick={() => navigate(`/recruitment/${opening.id}`)}
                >
                  <Table.Td>
                    <Text size="sm" fw={500}>
                      {localized(opening.title, i18n.language) || opening.reference}
                    </Text>
                    <Group gap={4} mt={2}>
                      <Badge size="xs" variant="default">
                        {opening.reference}
                      </Badge>
                      <Badge size="xs" variant="light" color="gray">
                        {opening.visibility.toLowerCase()}
                      </Badge>
                    </Group>
                  </Table.Td>
                  <Table.Td>
                    <OpeningBadge status={opening.status} />
                  </Table.Td>
                  <Table.Td>
                    <Text size="sm">
                      {opening.filled} of {opening.openings}
                    </Text>
                  </Table.Td>
                  <Table.Td>
                    <Text size="sm">
                      {opening.salaryRangeMin && opening.salaryRangeMax
                        ? `${Number(opening.salaryRangeMin).toLocaleString()} — ${Number(
                            opening.salaryRangeMax,
                          ).toLocaleString()}`
                        : "—"}
                    </Text>
                  </Table.Td>
                  <Table.Td>
                    <Text size="sm" c="dimmed">
                      {opening.closesOn ?? "—"}
                    </Text>
                  </Table.Td>
                  <Table.Td onClick={(event) => event.stopPropagation()}>
                    {(opening.status === "DRAFT" || opening.status === "ON_HOLD") && (
                      <Can permission={HR_PERMS.recruitment.manageJobOpening}>
                        <Button
                          size="compact-xs"
                          loading={publish.isPending}
                          onClick={() =>
                            publish.mutate({
                              id: opening.id,
                              closesOn: opening.closesOn ?? undefined,
                            })
                          }
                        >
                          Publish
                        </Button>
                      </Can>
                    )}
                  </Table.Td>
                </Table.Tr>
              ))}
              {!openings.isLoading && items.length === 0 && (
                <Table.Tr>
                  <Table.Td colSpan={6}>
                    <Text size="sm" c="dimmed" ta="center" py="lg">
                      No vacancies yet.
                    </Text>
                  </Table.Td>
                </Table.Tr>
              )}
            </Table.Tbody>
          </Table>
        </Table.ScrollContainer>
      </Card>

      <NewOpeningModal opened={creating} onClose={() => setCreating(false)} />
    </>
  );
}

function NewOpeningModal({
  opened,
  onClose,
}: {
  opened: boolean;
  onClose: () => void;
}) {
  const queryClient = useQueryClient();
  const [reference, setReference] = useState("");
  const [title, setTitle] = useState({ am: "", en: "" });
  const [positionId, setPositionId] = useState("");
  const [openings, setOpenings] = useState(1);
  const [visibility, setVisibility] = useState("INTERNAL");
  const [closesOn, setClosesOn] = useState<string | undefined>();
  const [salaryMin, setSalaryMin] = useState("");
  const [salaryMax, setSalaryMax] = useState("");

  const create = useMutation({
    mutationFn: () =>
      createOpening({
        reference,
        title,
        positionId: positionId || undefined,
        openings,
        visibility,
        closesOn,
        salaryRangeMin: salaryMin || undefined,
        salaryRangeMax: salaryMax || undefined,
      }),
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: ["job-openings"] });
      setReference("");
      setTitle({ am: "", en: "" });
      setPositionId("");
      onClose();
    },
  });

  return (
    <Modal opened={opened} onClose={onClose} title="New vacancy" centered size="lg">
      <Stack>
        {create.isError && (
          <Alert color="red" icon={<IconAlertTriangle size={18} />}>
            {apiErrorMessage(create.error)}
          </Alert>
        )}
        <TextInput
          label="Reference"
          required
          placeholder="VAC-2026-001"
          value={reference}
          onChange={(event) => setReference(event.currentTarget.value.toUpperCase())}
        />
        <BilingualTextInput label="Title" required value={title} onChange={setTitle} />
        <TextInput
          label="IAM position id"
          description="The post being filled. Optional now, but hiring needs one — the new employee has to have a place in the org chart."
          value={positionId}
          onChange={(event) => setPositionId(event.currentTarget.value)}
        />
        <Group grow>
          <NumberInput
            label="Seats"
            min={1}
            max={999}
            value={openings}
            onChange={(value) => setOpenings(Number(value) || 1)}
          />
          <Select
            label="Visible to"
            allowDeselect={false}
            value={visibility}
            onChange={(value) => setVisibility(value ?? "INTERNAL")}
            data={[
              { value: "INTERNAL", label: "Internal only" },
              { value: "EXTERNAL", label: "External only" },
              { value: "BOTH", label: "Both" },
            ]}
          />
        </Group>
        <Group grow>
          <TextInput
            label="Salary from"
            placeholder="8000.00"
            value={salaryMin}
            onChange={(event) => setSalaryMin(event.currentTarget.value)}
          />
          <TextInput
            label="to"
            placeholder="14000.00"
            value={salaryMax}
            onChange={(event) => setSalaryMax(event.currentTarget.value)}
          />
        </Group>
        <EthiopianDateInput
          label="Closes on"
          description="Required before it can be published."
          value={closesOn}
          onChange={setClosesOn}
        />
        <Group justify="flex-end">
          <Button variant="default" onClick={onClose}>
            Cancel
          </Button>
          <Button
            loading={create.isPending}
            disabled={!reference || !title.en}
            onClick={() => create.mutate()}
          >
            Create
          </Button>
        </Group>
      </Stack>
    </Modal>
  );
}
