"use client";

import { FormEvent, useMemo, useState } from "react";
import { Copy, Send } from "lucide-react";
import { useRouter } from "next/navigation";

import { Button } from "@/components/ui/button";
import { Dialog } from "@/components/ui/dialog";
import { Input } from "@/components/ui/input";
import { Select } from "@/components/ui/select";
import {
  DEFAULT_INVITATION_MAX_USES,
  DEFAULT_INVITATION_VALIDITY_DAYS,
  MAX_INVITATION_MAX_USES,
  MAX_INVITATION_VALIDITY_DAYS,
  MIN_INVITATION_MAX_USES,
  MIN_INVITATION_VALIDITY_DAYS,
} from "@/modules/core/invitation-limits";
import type { ApiResult } from "@/modules/core/server/api";
import type { Organization, OrganizationInvitation, RoleDefinition } from "@/modules/core/types";

type OrganizationInviteDialogProps = {
  open: boolean;
  organization: Organization;
  roles: RoleDefinition[];
  onClose: () => void;
};

export function getInviteHref(token: string): string {
  return `/register?invite=${encodeURIComponent(token)}`;
}

export function OrganizationInviteDialog({
  open,
  organization,
  roles,
  onClose,
}: OrganizationInviteDialogProps): React.ReactElement {
  const router = useRouter();
  const [message, setMessage] = useState("");
  const [lastInviteHref, setLastInviteHref] = useState("");
  const [isPending, setIsPending] = useState(false);
  const organizationRoles = useMemo(
    () => roles.filter((role) => role.scope === "organization" && role.organizationId === organization.id && role.isEnabled),
    [organization.id, roles],
  );

  function closeDialog(): void {
    if (isPending) {
      return;
    }

    setMessage("");
    setLastInviteHref("");
    onClose();
  }

  async function handleInviteSubmit(event: FormEvent<HTMLFormElement>): Promise<void> {
    event.preventDefault();
    setMessage("");
    setLastInviteHref("");
    const formData = new FormData(event.currentTarget);
    const roleId = String(formData.get("roleId") ?? "");
    if (!roleId) {
      setMessage("请选择邀请角色");
      return;
    }

    setIsPending(true);
    const response = await fetch(`/api/organizations/${organization.id}/invitations`, {
      method: "POST",
      headers: { "content-type": "application/json" },
      body: JSON.stringify({
        email: String(formData.get("email") ?? ""),
        maxUses: Number(formData.get("maxUses") ?? DEFAULT_INVITATION_MAX_USES),
        roleId,
        validityDays: Number(formData.get("validityDays") ?? DEFAULT_INVITATION_VALIDITY_DAYS),
      }),
    });
    const result = (await response.json()) as ApiResult<{ invitation: OrganizationInvitation }>;
    setIsPending(false);

    if (!result.success) {
      setMessage(result.reason);
      return;
    }

    const inviteHref = getInviteHref(result.invitation.token);
    setMessage(result.reason);
    setLastInviteHref(inviteHref);
    event.currentTarget.reset();
    router.refresh();
  }

  return (
    <Dialog
      description={`生成 ${organization.name} 的邀请链接，可限定邮箱、入组角色、有效期和使用次数。`}
      onClose={closeDialog}
      open={open}
      title="发起机构邀请"
    >
      <form className="grid gap-4" onSubmit={handleInviteSubmit}>
        <label className="grid gap-2 text-sm">
          <span className="font-medium">邮箱</span>
          <Input name="email" placeholder="可留空生成通用邀请" type="email" />
        </label>
        <label className="grid gap-2 text-sm">
          <span className="font-medium">角色</span>
          <Select
            aria-label="邀请角色"
            defaultValue=""
            disabled={organizationRoles.length === 0}
            key={organization.id}
            name="roleId"
            options={[
              { value: "", label: "选择邀请角色", disabled: true },
              ...organizationRoles.map((role) => ({ value: role.id, label: role.label })),
            ]}
            required
          />
        </label>
        <div className="grid gap-3 sm:grid-cols-2">
          <Input
            defaultValue={DEFAULT_INVITATION_VALIDITY_DAYS}
            label="有效期（天）"
            max={MAX_INVITATION_VALIDITY_DAYS}
            min={MIN_INVITATION_VALIDITY_DAYS}
            name="validityDays"
            required
            type="number"
          />
          <Input
            defaultValue={DEFAULT_INVITATION_MAX_USES}
            label="最大使用次数"
            max={MAX_INVITATION_MAX_USES}
            min={MIN_INVITATION_MAX_USES}
            name="maxUses"
            required
            type="number"
          />
        </div>
        {message ? (
          <p className="rounded-md bg-secondary px-3 py-2 text-sm text-secondary-foreground" role="status">
            {message}
          </p>
        ) : null}
        {lastInviteHref ? (
          <div className="flex flex-col gap-2 rounded-md border bg-secondary/20 p-3 text-sm sm:flex-row sm:items-center sm:justify-between">
            <span className="break-all text-muted-foreground">{lastInviteHref}</span>
            <Button
              onClick={() => void navigator.clipboard.writeText(lastInviteHref)}
              size="sm"
              type="button"
              variant="outline"
            >
              <Copy className="size-4" aria-hidden="true" />
              复制
            </Button>
          </div>
        ) : null}
        <div className="flex flex-col-reverse gap-2 sm:flex-row sm:justify-end">
          <Button disabled={isPending} onClick={closeDialog} type="button" variant="outline">
            取消
          </Button>
          <Button disabled={isPending || organizationRoles.length === 0} type="submit">
            <Send className="size-4" aria-hidden="true" />
            生成邀请
          </Button>
        </div>
      </form>
    </Dialog>
  );
}
