import React, { useState, useEffect } from "react";
import { createPortal } from "react-dom";
import { useTranslation } from "react-i18next";
import { Text, ActionIcon, ScrollArea } from "@mantine/core";
import CloseIcon from "@mui/icons-material/Close";
import {
  CardModalPhase,
  CARD_MODAL_TIMINGS,
} from "@app/hooks/useCardModalAnimation";

interface CardExpansionModalProps {
  phase: CardModalPhase;
  cardRect: DOMRect | null;
  textExpanded: boolean;
  onClose: () => void;
  icon: React.ReactNode;
  count: number;
  labelSingular: string;
  labelPlural: string;
  children: React.ReactNode;
  footer?: React.ReactNode;
  toolbar?: React.ReactNode;
  widthRem?: number;
  heightRem?: number;
  /** Replace ScrollArea with a flex-fill container so children can expand to full body height */
  fillHeight?: boolean;
}

const MODAL_W_REM = 56;
const MODAL_H_REM = 38;
const HEADER_H_REM = 3.5;
const MODAL_TOP_FRACTION = 0.12;
const EASING = "cubic-bezier(0.22,1,0.36,1)";

export function CardExpansionModal({
  phase,
  cardRect,
  textExpanded,
  onClose,
  icon,
  count,
  labelSingular,
  labelPlural,
  children,
  footer,
  toolbar,
  widthRem,
  heightRem,
  fillHeight,
}: CardExpansionModalProps) {
  const { t } = useTranslation();
  const [viewportW, setViewportW] = useState(window.innerWidth);
  const [viewportH, setViewportH] = useState(window.innerHeight);

  useEffect(() => {
    const handler = () => {
      setViewportW(window.innerWidth);
      setViewportH(window.innerHeight);
    };
    window.addEventListener("resize", handler);
    return () => window.removeEventListener("resize", handler);
  }, []);

  if (phase === "closed" || !cardRect) return null;

  const rootFontSize = parseFloat(
    getComputedStyle(document.documentElement).fontSize,
  );
  const modalW = Math.min(
    (widthRem ?? MODAL_W_REM) * rootFontSize,
    viewportW * 0.9,
  );
  const modalH = Math.min(
    (heightRem ?? MODAL_H_REM) * rootFontSize,
    viewportH * 0.85,
  );
  const headerH = HEADER_H_REM * rootFontSize;
  const finalLeft = (viewportW - modalW) / 2;
  const finalTop = Math.min(
    viewportH * MODAL_TOP_FRACTION,
    viewportH - modalH - 16,
  );

  const isAtCard = phase === "entering" || phase === "closing-header";
  const isAtHeader = phase === "header-open";

  const cardH = isAtCard ? cardRect.height : isAtHeader ? headerH : modalH;

  const getTransition = () => {
    const s = CARD_MODAL_TIMINGS;
    if (phase === "header-open")
      return `top ${s.headerStretch}ms ${EASING}, left ${s.headerStretch}ms ${EASING}, width ${s.headerStretch}ms ${EASING}, height ${s.headerStretch}ms ${EASING}`;
    if (phase === "open") return `height ${s.bodyDrop}ms ${EASING}`;
    if (phase === "closing-body") return `height ${s.closeBody}ms ease-in`;
    if (phase === "closing-header")
      return `top ${s.closeStretch}ms ${EASING}, left ${s.closeStretch}ms ${EASING}, width ${s.closeStretch}ms ${EASING}, height ${s.closeStretch}ms ${EASING}, opacity ${s.closeStretch}ms ease`;
    return "none";
  };

  const backdropOpacity =
    phase === "entering" || phase === "closing-header" ? 0 : 1;
  const cardOpacity = phase === "closing-header" ? 0 : 1;

  const showBody = phase === "open" || phase === "closing-body";

  return createPortal(
    <div style={{ position: "fixed", inset: 0, zIndex: 300 }}>
      <div
        onClick={onClose}
        style={{
          position: "absolute",
          inset: 0,
          backgroundColor: "rgba(0,0,0,0.55)",
          opacity: backdropOpacity,
          transition: "opacity 220ms ease",
          willChange: "opacity",
        }}
      />

      <div
        style={{
          position: "fixed",
          top: isAtCard ? cardRect.top : finalTop,
          left: isAtCard ? cardRect.left : finalLeft,
          width: isAtCard ? cardRect.width : modalW,
          height: cardH,
          opacity: cardOpacity,
          transition: getTransition(),
          willChange: "top, left, width, height, opacity",
          borderRadius: "var(--mantine-radius-md)",
          overflow: "hidden",
          backgroundColor: "var(--bg-toolbar)",
          display: "flex",
          flexDirection: "column",
          boxShadow: "0 1.5rem 3rem rgba(0,0,0,0.3)",
        }}
      >
        {/* Header */}
        <div
          style={{
            position: "relative",
            height: headerH,
            flexShrink: 0,
            borderBottom: "0.0625rem solid var(--border-subtle)",
            overflow: "hidden",
          }}
        >
          <div
            style={{
              position: "absolute",
              inset: 0,
              display: "flex",
              alignItems: "center",
              justifyContent: "center",
            }}
          >
            <div
              style={{
                position: "absolute",
                left: "1rem",
                display: "flex",
                alignItems: "center",
              }}
            >
              {icon}
            </div>

            <Text
              component="span"
              fw={800}
              style={{ fontSize: "1.375rem", lineHeight: 1, margin: 0 }}
            >
              {count}
            </Text>
            <div
              style={{
                maxWidth: textExpanded ? "16rem" : "0",
                opacity: textExpanded ? 1 : 0,
                overflow: "hidden",
                whiteSpace: "nowrap",
                display: "flex",
                alignItems: "center",
                transition: `max-width 100ms ${EASING}, opacity 80ms ease`,
              }}
            >
              <Text
                component="span"
                c="dimmed"
                style={{
                  fontSize: "1rem",
                  paddingLeft: "0.5rem",
                  lineHeight: 1,
                  margin: 0,
                }}
              >
                {count === 1 ? labelSingular : labelPlural}
              </Text>
            </div>

            <ActionIcon
              variant="subtle"
              size="lg"
              color="gray"
              onClick={onClose}
              aria-label={t("close", "Close")}
              style={{
                position: "absolute",
                top: "0.25rem",
                right: "0.375rem",
              }}
            >
              <CloseIcon style={{ fontSize: "1.25rem" }} />
            </ActionIcon>
          </div>
        </div>

        {showBody && (
          <div
            style={{
              flex: 1,
              display: "flex",
              flexDirection: "column",
              minHeight: 0,
              backgroundColor: "var(--bg-toolbar)",
            }}
          >
            {toolbar && (
              <div
                style={{
                  flexShrink: 0,
                  borderBottom: "0.0625rem solid var(--border-subtle)",
                }}
              >
                {toolbar}
              </div>
            )}
            {fillHeight ? (
              <div
                style={{
                  flex: 1,
                  minHeight: 0,
                  padding: "0.75rem 1rem",
                  display: "flex",
                  flexDirection: "column",
                }}
              >
                {children}
              </div>
            ) : (
              <ScrollArea style={{ flex: 1, minHeight: 0 }}>
                <div
                  style={{
                    padding: "0.75rem 1rem",
                    backgroundColor: "var(--bg-toolbar)",
                  }}
                >
                  {children}
                </div>
              </ScrollArea>
            )}
            {footer && (
              <div
                style={{
                  padding: "0.75rem 1rem",
                  borderTop: "0.0625rem solid var(--border-subtle)",
                  flexShrink: 0,
                }}
              >
                {footer}
              </div>
            )}
          </div>
        )}
      </div>
    </div>,
    document.body,
  );
}
