import { i18nMessage, usePlatformLanguage } from "../../i18n/LanguageContext";
import { useEffect, useId, useMemo, useRef, useState } from "react";
import type { CSSProperties, KeyboardEvent } from "react";
import { createPortal } from "react-dom";
import Button from "../Button";
import {
  addressDisplayName,
  dedupeAddresses,
  isValidEmailAddress,
  normalizeEmailAddress,
  parseMailboxAddressText,
  type MailboxAddress } from
"../../utils/emailAddresses";

type EmailAddressInputProps = {
  value: MailboxAddress[];
  onChange?: (value: MailboxAddress[]) => void;
  onAddressAdded?: (address: MailboxAddress) => void;
  onSuggestionQueryChange?: (query: string) => void;
  suggestions?: MailboxAddress[];
  allowMultiple?: boolean;
  clearOnAdd?: boolean;
  disabled?: boolean;
  addLabel?: string;
  namePlaceholder?: string;
  emailPlaceholder?: string;
  emptyText?: string;
  compact?: boolean;
  showAddButton?: boolean;
};

export default function EmailAddressInput({
  value,
  onChange,
  onAddressAdded,
  onSuggestionQueryChange,
  suggestions = [],
  allowMultiple = true,
  clearOnAdd = false,
  disabled = false,
  addLabel = "i18n:govoplan-core.add.61cc55aa",
  namePlaceholder = "i18n:govoplan-core.name.709a2322",
  emailPlaceholder = "email@example.org",
  emptyText = "i18n:govoplan-core.no_address_added_yet.809c4247",
  compact = false,
  showAddButton
}: EmailAddressInputProps) {
  const { translateText } = usePlatformLanguage();
  const inputId = useId();
  const normalizedValue = useMemo(() => dedupeAddresses(value), [value]);
  const normalizedSuggestions = useMemo(() => dedupeAddresses(suggestions), [suggestions]);
  const [entryText, setEntryText] = useState("");
  const [dialogOpen, setDialogOpen] = useState(false);
  const [dialogName, setDialogName] = useState("");
  const [dialogEmail, setDialogEmail] = useState("");
  const [error, setError] = useState("");
  const [popoverStyle, setPopoverStyle] = useState<CSSProperties>({});
  const lastSuggestionQueryRef = useRef<string | null>(null);
  const addButtonRef = useRef<HTMLButtonElement | null>(null);
  const canUseAddButton = showAddButton ?? allowMultiple;

  useEffect(() => {
    const query = entryText.trim();
    if (query === "" && lastSuggestionQueryRef.current === null) return;
    if (query === lastSuggestionQueryRef.current) return;
    lastSuggestionQueryRef.current = query;
    onSuggestionQueryChange?.(query);
  }, [entryText, onSuggestionQueryChange]);

  const filteredSuggestions = useMemo(() => {
    const query = entryText.trim().toLowerCase();
    if (!query) return normalizedSuggestions.slice(0, 6);
    return normalizedSuggestions.
    filter((item) => `${item.name ?? ""} ${item.email}`.toLowerCase().includes(query)).
    slice(0, 6);
  }, [entryText, normalizedSuggestions]);

  useEffect(() => {
    if (!dialogOpen) return;

    function updatePopoverPosition() {
      const trigger = addButtonRef.current;
      if (!trigger) return;
      const rect = trigger.getBoundingClientRect();
      const viewportPadding = 16;
      const width = Math.min(360, Math.max(280, window.innerWidth - viewportPadding * 2));
      const estimatedHeight = 250;
      const left = Math.min(Math.max(viewportPadding, rect.right - width), window.innerWidth - width - viewportPadding);
      const belowTop = rect.bottom + 8;
      const aboveTop = rect.top - estimatedHeight - 8;
      const top = belowTop + estimatedHeight > window.innerHeight && aboveTop > viewportPadding ? aboveTop : belowTop;
      setPopoverStyle({
        position: "fixed",
        top,
        left,
        width,
        zIndex: 10000
      });
    }

    updatePopoverPosition();
    window.addEventListener("resize", updatePopoverPosition);
    window.addEventListener("scroll", updatePopoverPosition, true);
    return () => {
      window.removeEventListener("resize", updatePopoverPosition);
      window.removeEventListener("scroll", updatePopoverPosition, true);
    };
  }, [dialogOpen]);

  function removeAddress(emailToRemove: string) {
    if (disabled) return;
    onChange?.(normalizedValue.filter((address) => address.email !== emailToRemove));
    setError("");
  }

  function commitAddress(candidate: MailboxAddress | null, sourceText = "") {
    if (disabled) return false;
    if (!candidate?.email) {
      setError(sourceText ? "i18n:govoplan-core.use_a_valid_address_such_as_name_email_example_o.39cdbc3c" : "i18n:govoplan-core.enter_an_email_address_first.6d55dfd1");
      return false;
    }

    const normalized = normalizeEmailAddress(candidate);
    if (!isValidEmailAddress(normalized.email)) {
      setError("i18n:govoplan-core.enter_a_valid_email_address.2e09edea");
      return false;
    }
    if (allowMultiple && normalizedValue.some((address) => address.email === normalized.email)) {
      setError("i18n:govoplan-core.this_address_is_already_listed.0f6d0ff2");
      return false;
    }

    onAddressAdded?.(normalized);
    if (!clearOnAdd) {
      const nextValue = allowMultiple ? dedupeAddresses([...normalizedValue, normalized]) : [normalized];
      onChange?.(nextValue);
    }
    setEntryText("");
    setDialogName("");
    setDialogEmail("");
    setDialogOpen(false);
    setError("");
    return true;
  }

  function commitTypedAddress() {
    const text = entryText.trim();
    if (!text) return;
    commitAddress(parseMailboxAddressText(text), text);
  }

  function commitDialogAddress() {
    commitAddress({ name: dialogName, email: dialogEmail }, `${dialogName} ${dialogEmail}`);
  }

  function handleTextKeyDown(event: KeyboardEvent<HTMLTextAreaElement>) {
    if (event.key === "Enter" && !event.shiftKey) {
      event.preventDefault();
      commitTypedAddress();
      return;
    }
    if (event.key === "Backspace" && !entryText && normalizedValue.length > 0 && !disabled) {
      event.preventDefault();
      const last = normalizedValue[normalizedValue.length - 1];
      removeAddress(last.email);
    }
  }

  function applySuggestion(address: MailboxAddress) {
    commitAddress(address);
  }

  const addressDialog = dialogOpen && canUseAddButton && !disabled ? createPortal(
    <div
      className="email-address-popover"
      style={popoverStyle}
      role="dialog"
      aria-modal="false"
      aria-labelledby={`${inputId}-dialog-title`}
      onKeyDown={(event) => {
        if (event.key === "Escape") setDialogOpen(false);
      }}>
      
      <h4 id={`${inputId}-dialog-title`}>{translateText("i18n:govoplan-core.add_address.a71075c4")}</h4>
      <label>
        <span>{translateText("i18n:govoplan-core.name.709a2322")}</span>
        <input value={dialogName} onChange={(event) => setDialogName(event.target.value)} placeholder={translateText(namePlaceholder)} autoFocus />
      </label>
      <label>
        <span>{translateText("i18n:govoplan-core.email_address.c94d3175")}</span>
        <input value={dialogEmail} onChange={(event) => setDialogEmail(event.target.value)} placeholder={emailPlaceholder} inputMode="email" />
      </label>
      <div className="button-row compact-actions">
        <Button type="button" onClick={() => setDialogOpen(false)}>{translateText("i18n:govoplan-core.cancel.77dfd213")}</Button>
        <Button type="button" variant="primary" onClick={commitDialogAddress}>{translateText(addLabel)}</Button>
      </div>
    </div>,
    document.body
  ) : null;

  return (
    <div className={`email-address-input ${compact ? "compact" : ""} ${disabled ? "disabled" : ""} ${canUseAddButton ? "has-add-button" : ""}`}>
      <div className={`email-address-editor ${error ? "has-error" : ""}`}>
        <div className="email-chip-list" aria-live="polite">
          {normalizedValue.length === 0 && !entryText && <span className="email-chip-empty">{translateText(emptyText)}</span>}
          {normalizedValue.map((address) => {
            const valid = isValidEmailAddress(address.email);
            return (
              <span className={`email-chip ${valid ? "" : "invalid"}`} key={address.email} title={valid ? address.email : translateText("i18n:govoplan-core.invalid_email_address.9e4ee6d7")}>
                <span className="email-chip-main">{addressDisplayName(address)}</span>
                {address.name && <span className="email-chip-address">{address.email}</span>}
                {!disabled &&
                <button type="button" className="email-chip-remove" aria-label={i18nMessage("i18n:govoplan-core.remove_value.a2d40d33", { value0: address.email })} onClick={() => removeAddress(address.email)}>
                    ×
                  </button>
                }
              </span>);

          })}
        </div>
        {!disabled &&
        <>
            <textarea
            id={inputId}
            className="email-address-textarea"
            rows={1}
            value={entryText}
            onChange={(event) => {
              setEntryText(event.target.value);
              setError("");
            }}
            onKeyDown={handleTextKeyDown}
            placeholder={translateText(i18nMessage("i18n:govoplan-core.value_value.27085f09", { value0: translateText(namePlaceholder), value1: emailPlaceholder }))}
            aria-label={translateText("i18n:govoplan-core.type_a_name_and_email_address_then_press_enter.7c8d43f0")} />
          
            {canUseAddButton &&
          <button ref={addButtonRef} type="button" className="email-address-plus" aria-label={translateText("i18n:govoplan-core.open_address_form.f8ee560f")} title={translateText("i18n:govoplan-core.add_address_with_form.13b3b3e7")} onClick={() => setDialogOpen((open) => !open)}>
                +
              </button>
          }
          </>
        }
      </div>

      {!disabled && filteredSuggestions.length > 0 && entryText.trim() &&
      <div className="email-address-suggestions" role="listbox" aria-label={translateText("i18n:govoplan-core.address_suggestions.45ba4a20")}>
          {filteredSuggestions.map((item) =>
        <button type="button" key={item.email} onClick={() => applySuggestion(item)} role="option">
              <span>{addressDisplayName(item)}</span>
              {item.name && <small>{item.email}</small>}
            </button>
        )}
        </div>
      }
      {error && <p className="form-help danger-text">{translateText(error)}</p>}
      {addressDialog}
    </div>);

}
