import { Alert, Button, Loader, Modal, Radio, Stack, Text } from "@mantine/core";
import { useMutation, useQuery } from "@tanstack/react-query";
import { KeyRound } from "lucide-react";
import { useState } from "react";

import { useAuth } from "@/auth/useAuth";
import { useToast } from "@/hooks/use-toast";
import { FREIGHT_PERMS, hasPermission } from "@/lib/permissions";
import { api } from "@/services/api";
import type { Company, ResetChannel } from "@/types/customer";

export interface ResetPasswordActionProps {
  company: Pick<Company, "id">;
}

/**
 * Staff-triggered password reset. Sends a single-use link to the customer's
 * primary contact; the customer opens it and picks their own new password. No
 * credential is ever shown to or handled by staff.
 */
export default function ResetPasswordAction({
  company,
}: ResetPasswordActionProps) {
  const { user } = useAuth();
  const { toast } = useToast();
  const [opened, setOpened] = useState(false);
  const [channel, setChannel] = useState<ResetChannel>("phone");

  const allowed = hasPermission(user, FREIGHT_PERMS.customers.resetPassword);

  // The destination is the primary contact's IAM account, not the company
  // record — those are different fields and routinely hold different values, so
  // showing `company.phone` here would tell staff the wrong number. Only fetched
  // once the modal is open.
  const targetQuery = useQuery(
    api.customers.resetTarget.queryOptions({
      input: { companyId: company.id },
      enabled: allowed && opened,
    }),
  );
  const target = targetQuery.data;

  const { mutate, isPending } = useMutation(
    api.customers.resetPassword.mutationOptions({
      onSuccess: (result) => {
        setOpened(false);
        toast({
          title: "Reset link sent",
          description: `The customer can set a new password using the link sent to ${result.maskedTarget}. It expires in 24 hours.`,
        });
      },
      onError: (error) => {
        toast({
          title: "Could not send reset link",
          description: error.message,
          variant: "destructive",
        });
      },
    }),
  );

  if (!allowed) return null;

  // SMS is domestic-only: a foreign number counts as unavailable, same as a
  // missing one, so staff can't send a link that will never arrive.
  const phoneUsable = !!target?.phone && target.phoneIsDomestic !== false;
  const channelMissing =
    !!target && (channel === "email" ? !target.email : !phoneUsable);

  return (
    <>
      <Button
        variant="default"
        leftSection={<KeyRound size={16} />}
        onClick={() => setOpened(true)}
      >
        Reset password
      </Button>

      <Modal
        opened={opened}
        onClose={() => setOpened(false)}
        title="Send a password-reset link"
        centered
      >
        <Stack gap="md">
          <Text size="sm" c="dimmed">
            We&apos;ll send a single-use link to this customer&apos;s primary
            contact. They choose their own new password — you will not see it.
            The link expires in 24 hours.
          </Text>

          {targetQuery.isLoading ? (
            <Stack align="center" py="md">
              <Loader size="sm" />
            </Stack>
          ) : targetQuery.isError ? (
            <Alert color="red" variant="light">
              {targetQuery.error.message}
            </Alert>
          ) : target ? (
            <>
              <Radio.Group
                value={channel}
                onChange={(v) => setChannel(v as ResetChannel)}
                label={`Send the link to ${target.name || "the primary contact"} via`}
              >
                <Stack gap="xs" mt="xs">
                  <Radio
                    value="phone"
                    label="SMS"
                    disabled={!phoneUsable}
                    description={
                      !target.phone
                        ? "No phone number on this account"
                        : target.phoneIsDomestic === false
                          ? `${target.phone} — foreign number, SMS unavailable; use email`
                          : target.phone
                    }
                  />
                  <Radio
                    value="email"
                    label="Email"
                    disabled={!target.email}
                    description={
                      target.email ?? "No email address on this account"
                    }
                  />
                </Stack>
              </Radio.Group>

              <Text size="xs" c="dimmed">
                These are the primary contact&apos;s own login details, which may
                differ from the company contact details on the profile.
              </Text>

              <Button
                color="edr-green"
                loading={isPending}
                disabled={channelMissing}
                onClick={() => mutate({ companyId: company.id, channel })}
              >
                Send reset link
              </Button>
            </>
          ) : null}
        </Stack>
      </Modal>
    </>
  );
}
