import { useEffect, useRef, useState } from "react";
import { Button, IconButton } from "./Button.js";
import { Icon } from "./Icon.js";
import { Select, type SelectOption } from "./Select.js";
import { TextField } from "./Field.js";
import { Window, WindowFooterActions } from "./Window.js";

export interface ShareAccessMember<Role extends string = string> {
  id: string;
  name: string;
  email: string;
  role: Role;
  roleLabel?: string;
  avatarUrl?: string;
  immutable?: boolean;
}

export interface ShareAccessModalProps<Role extends string = string> {
  open: boolean;
  resourceName: string;
  members: readonly ShareAccessMember<Role>[];
  roleOptions: Array<SelectOption<Role>>;
  inviteEmail: string;
  inviteRole: Role;
  canManage?: boolean;
  pending?: boolean;
  message?: string;
  messageTone?: "neutral" | "success" | "danger" | "accent";
  onInviteEmailChange: (email: string) => void;
  onInviteRoleChange: (role: Role) => void;
  onInvite: () => void | Promise<void>;
  onMemberRoleChange?: (member: ShareAccessMember<Role>, role: Role) => void;
  onMemberRemove?: (member: ShareAccessMember<Role>) => void;
  onClose: () => void;
}

function initials(name: string, email: string) {
  const words = (name || email).split(/[\s._@-]+/).filter(Boolean);
  return `${words[0]?.[0] ?? "N"}${words[1]?.[0] ?? words[0]?.[1] ?? ""}`.toUpperCase();
}

export function ShareAccessModal<Role extends string>({
  open,
  resourceName,
  members,
  roleOptions,
  inviteEmail,
  inviteRole,
  canManage = true,
  pending = false,
  message,
  messageTone = "neutral",
  onInviteEmailChange,
  onInviteRoleChange,
  onInvite,
  onMemberRoleChange,
  onMemberRemove,
  onClose,
}: ShareAccessModalProps<Role>) {
  const [membersOpen, setMembersOpen] = useState(false);
  const membersRootRef = useRef<HTMLElement>(null);

  useEffect(() => {
    if (!open) setMembersOpen(false);
  }, [open]);

  useEffect(() => {
    if (!membersOpen) return;
    const handlePointerDown = (event: PointerEvent) => {
      if (!(event.target instanceof Node)) return;
      if (event.target instanceof Element && event.target.closest(".nodedc-dropdown-surface")) return;
      if (!membersRootRef.current?.contains(event.target)) setMembersOpen(false);
    };
    const handleKeyDown = (event: KeyboardEvent) => {
      if (event.key !== "Escape") return;
      // An open nested dropdown owns the first Escape press. Let it close and
      // restore focus without collapsing the surrounding members disclosure.
      if (document.querySelector(".nodedc-dropdown-surface")) return;
      event.preventDefault();
      event.stopImmediatePropagation();
      setMembersOpen(false);
    };
    document.addEventListener("pointerdown", handlePointerDown, true);
    document.addEventListener("keydown", handleKeyDown, true);
    return () => {
      document.removeEventListener("pointerdown", handlePointerDown, true);
      document.removeEventListener("keydown", handleKeyDown, true);
    };
  }, [membersOpen]);

  return (
    <Window
      open={open}
      title="Поделиться графом"
      subtitle={resourceName.toUpperCase()}
      className="nodedc-share-access-window"
      closeOnBackdrop={false}
      onClose={onClose}
      footer={
        <WindowFooterActions>
          <Button onClick={onClose} disabled={pending}>Отменить</Button>
          {canManage ? (
            <Button variant="primary" onClick={() => void onInvite()} disabled={pending || !inviteEmail.trim()}>
              {pending ? "Сохранение..." : "Поделиться"}
            </Button>
          ) : null}
        </WindowFooterActions>
      }
    >
      <div className="nodedc-share-access">
        <section ref={membersRootRef} className="nodedc-share-access__members" aria-label="Пользователи с доступом">
          <span className="nodedc-share-access__section-label">Уже добавлены</span>
          {members.length ? (
            <>
              <button
                type="button"
                className="nodedc-share-access__summary"
                aria-label={`Пользователи с доступом: ${members.length}`}
                aria-expanded={membersOpen}
                onClick={() => setMembersOpen((current) => !current)}
              >
                <span className="nodedc-share-access__summary-avatars" aria-hidden="true">
                  {members.slice(0, 3).map((member, index) => (
                    <span className="nodedc-share-access__summary-avatar" style={{ left: index * 18, zIndex: 10 + index }} key={member.id}>
                      {member.avatarUrl ? <img src={member.avatarUrl} alt="" /> : initials(member.name, member.email)}
                    </span>
                  ))}
                </span>
                <span className="nodedc-share-access__summary-count">{members.length}</span>
              </button>
            </>
          ) : <div className="nodedc-share-access__empty">Пока никому не открыт доступ</div>}
          {membersOpen ? (
            <div className="nodedc-share-access__member-list">
              {members.map((member) => (
              <div className="nodedc-share-access__member" key={member.id}>
                <span className="nodedc-share-access__avatar" aria-hidden="true">
                  {member.avatarUrl ? <img src={member.avatarUrl} alt="" /> : initials(member.name, member.email)}
                </span>
                <span className="nodedc-share-access__identity">
                  <strong>{member.name || member.email}</strong>
                  {member.name && member.name !== member.email ? <small>{member.email}</small> : null}
                </span>
                {canManage && !member.immutable && onMemberRoleChange ? (
                  <Select
                    value={member.role}
                    label={`Роль ${member.email}`}
                    options={roleOptions}
                    minMenuWidth={150}
                    onChange={(role) => onMemberRoleChange(member, role)}
                  />
                ) : <span className="nodedc-share-access__role">{member.roleLabel ?? member.role}</span>}
                {canManage && !member.immutable && onMemberRemove ? (
                  <IconButton label={`Удалить доступ ${member.email}`} onClick={() => onMemberRemove(member)}>
                    <Icon name="trash" />
                  </IconButton>
                ) : null}
              </div>
              ))}
            </div>
          ) : null}
        </section>

        {canManage ? (
          <div className="nodedc-share-access__invite">
            <TextField
              label="Пользователь"
              type="email"
              value={inviteEmail}
              disabled={pending}
              placeholder="email@company.ru"
              onChange={(event) => onInviteEmailChange(event.target.value)}
            />
            <div className="nodedc-field">
              <span className="nodedc-field__label-row"><span className="nodedc-field__label">Роль</span></span>
              <Select
                value={inviteRole}
                label="Роль доступа"
                options={roleOptions}
                disabled={pending}
                onChange={(role) => onInviteRoleChange(role)}
              />
            </div>
          </div>
        ) : (
          <div className="nodedc-share-access__readonly">
            <strong>Вы не можете пригласить пользователя</strong>
            <span>Попросите владельца изменить ваш уровень доступа.</span>
          </div>
        )}

        {message ? <div className="nodedc-share-access__message" data-tone={messageTone}>{message}</div> : null}
      </div>
    </Window>
  );
}

export interface ShareLinkModalProps {
  open: boolean;
  title?: string;
  link: string;
  hint?: string;
  copyLabel?: string;
  onCopy?: (link: string) => void | Promise<void>;
  onClose: () => void;
}

export function ShareLinkModal({
  open,
  title = "Ссылка на модель",
  link,
  hint = "Ссылка открывает текущую модель и сохранённую точку обзора.",
  copyLabel = "Скопировать",
  onCopy,
  onClose,
}: ShareLinkModalProps) {
  const [copied, setCopied] = useState(false);

  useEffect(() => {
    if (!open) setCopied(false);
  }, [open]);

  const copy = async () => {
    if (onCopy) await onCopy(link);
    else await navigator.clipboard.writeText(link);
    setCopied(true);
  };

  return (
    <Window
      open={open}
      title={title}
      size="sm"
      onClose={onClose}
      footer={
        <>
          <Button onClick={onClose}>Закрыть</Button>
          <WindowFooterActions>
            <Button variant="primary" icon={<Icon name={copied ? "check" : "copy"} />} onClick={() => void copy()} disabled={!link}>
              {copied ? "Скопировано" : copyLabel}
            </Button>
          </WindowFooterActions>
        </>
      }
    >
      <TextField label="Публичная ссылка" value={link} readOnly description={hint} />
    </Window>
  );
}
