import { useMemo, useRef, useState } from "react";
import { ReactPhotoSphereViewer } from "react-photo-sphere-viewer";
import { ReactMarkdownComponent } from "../../ReactMarkdown";
import { ThreeViewErrorBoundary } from "../../MediaViewer/ThreeViewErrorBoundary";
import {
  SightFrameThreeView,
  ThreeViewHandle,
} from "./SightFrameThreeView";
import { MinusIcon, PlusIcon } from "./SightFrameThreeViewIcons";
import "./SightFramePreview.css";

interface ArticleMedia {
  id: string;
  media_type: number;
  filename: string;
}

interface Article {
  id: number;
  heading: string;
  body: string;
  media: ArticleMedia[];
}

interface PreviewMediaData {
  id: string;
  media_type: number;
  filename?: string;
}

interface SightFramePreviewProps {
  sightName: string;
  previewMedia: PreviewMediaData | null;
  articles: Article[];
  onArticleSelect: (index: number) => void;
  previewFontSize?: number;
}

// Matches SightFrame.jsx renderCurrentMedia — same structure, same CSS classes
function renderCurrentMedia(
  media: PreviewMediaData | ArticleMedia | null,
  token: string,
  threeViewResetKey: number,
  threeViewControlRef: React.MutableRefObject<ThreeViewHandle | null>,
  onZoomIn: () => void,
  onZoomOut: () => void,
  onThreeViewReset: () => void
) {
  if (!media) return null;

  const src = `${import.meta.env.VITE_KRBL_MEDIA}${media.id}/download?token=${token}`;
  const className = "sfp-sight-frame-media-item";

  switch (media.media_type) {
    // image (1), gif (3), sprite (4)
    case 1:
    case 3:
    case 4:
      return (
        <img
          src={src}
          alt=""
          className={className}
          onError={(e) => {
            (e.target as HTMLImageElement).style.display = "none";
          }}
        />
      );

    // video
    case 2:
      return (
        <video
          muted
          autoPlay
          loop
          playsInline
          className={className}
          onError={(e) => {
            (e.target as HTMLVideoElement).style.display = "none";
          }}
        >
          <source src={src} type="video/mp4" />
        </video>
      );

    // panorama
    case 5:
      return (
        <div
          className={`${className} panorama-container`}
          style={{ isolation: "isolate" }}
        >
          <ReactPhotoSphereViewer
            src={src}
            width={"100%"}
            height={"100%"}
          />
        </div>
      );

    // 3d
    case 6:
      return (
        <div className={className} style={{ position: "relative" }}>
          <ThreeViewErrorBoundary
            resetKey={`sfp-${media.id}-${threeViewResetKey}`}
            onReset={onThreeViewReset}
          >
            <SightFrameThreeView
              key={`sfp-3d-${media.id}-${threeViewResetKey}`}
              fileUrl={src}
              width={"100%"}
              height={"100%"}
              controlRef={threeViewControlRef}
            />
          </ThreeViewErrorBoundary>
          <div className="sfp-three-d-controls-bar">
            <button
              type="button"
              className="sfp-three-d-control-btn"
              title="Уменьшить"
              onPointerUp={onZoomOut}
            >
              <MinusIcon />
            </button>
            <button
              type="button"
              className="sfp-three-d-control-btn"
              title="Увеличить"
              onPointerUp={onZoomIn}
            >
              <PlusIcon />
            </button>
          </div>
        </div>
      );

    default:
      return (
        <div className={className}>
          <div className="sfp-sight-frame-media-placeholder">
            Неподдерживаемый тип медиа
          </div>
        </div>
      );
  }
}

export function SightFramePreview({
  sightName,
  previewMedia,
  articles,
  onArticleSelect,
  previewFontSize,
}: SightFramePreviewProps) {
  const token = localStorage.getItem("token") ?? "";

  // -1 = intro (section 0 in SightFrame)
  const [selectedSection, setSelectedSection] = useState<number>(-1);
  const [threeViewResetKey, setThreeViewResetKey] = useState(0);
  const threeViewControlRef = useRef<ThreeViewHandle | null>(null);

  const currentArticle =
    selectedSection >= 0 && selectedSection < articles.length
      ? articles[selectedSection]
      : null;

  const currentMedia: PreviewMediaData | ArticleMedia | null = currentArticle
    ? (currentArticle.media[0] ?? null)
    : previewMedia;

  const isCurrentMedia3D = currentMedia?.media_type === 6;

  // Replicates processedSightName from SightFrame.jsx
  const processedSightName = useMemo(() => {
    if (!sightName) return sightName;
    const namePattern =
      /([А-Яа-яA-Za-z0-9]\. [А-Яа-яA-Za-z0-9]\. [А-Яа-яA-Za-z0-9]+)/g;
    const parts = sightName.split(namePattern);
    if (parts.length > 1) {
      return parts.map((part, index) => {
        const initialsPattern =
          /^[А-Яа-яA-Za-z0-9]\. [А-Яа-яA-Za-z0-9]\. [А-Яа-яA-Za-z0-9]+$/;
        if (initialsPattern.test(part)) {
          return (
            <span key={index}>
              <br />
              {part}
            </span>
          );
        }
        return <span key={index}>{part}</span>;
      });
    }
    return sightName;
  }, [sightName]);

  // Replicates titleLineHeight from SightFrame.jsx
  const titleLineHeight = useMemo(() => {
    if (!sightName) return "120%";
    const textLength = sightName.length;
    const calculatedLineHeight = Math.max(
      100,
      Math.min(120, 120 - (textLength / 10) * 1)
    );
    return `${calculatedLineHeight}%`;
  }, [sightName]);

  const isIntro = selectedSection === -1;

  return (
    <div className="sfp-sight-frame">
      {/* media stack — always rendered, matches .sight-frame-media-stack */}
      <div
        className={`sfp-sight-frame-media-stack${isCurrentMedia3D ? " three-d-view" : ""}`}
      >
        {currentMedia ? (
          renderCurrentMedia(
            currentMedia,
            token,
            threeViewResetKey,
            threeViewControlRef,
            () => threeViewControlRef.current?.zoomIn?.(),
            () => threeViewControlRef.current?.zoomOut?.(),
            () => setThreeViewResetKey((k) => k + 1)
          )
        ) : (
          <div className="sfp-sight-frame-media-placeholder">
            {isIntro ? "Медиа не добавлено" : "Нет медиа"}
          </div>
        )}
      </div>

      {/* content */}
      <div className="sfp-sight-frame-content">
        {/* title: intro-title (300px, 40px centered) or regular (24px with border) */}
        <div
          className={`sfp-sight-frame-title${isIntro ? " sfp-intro-title" : ""}`}
          style={{
            lineHeight: isIntro ? undefined : titleLineHeight,
            ...(isIntro && previewFontSize != null
              ? { fontSize: `${previewFontSize}px` }
              : {}),
          }}
        >
          <p
            style={{
              whiteSpace: "normal",
              wordBreak: "break-word",
              overflowWrap: "break-word",
            }}
          >
            {isIntro ? processedSightName : sightName}
          </p>
        </div>

        {/* text body — only for article sections */}
        {!isIntro && currentArticle && (
          <div className="sfp-sight-frame-text-wrapper">
            <div className="sfp-sight-frame-text">
              <ReactMarkdownComponent value={currentArticle.body} />
            </div>
          </div>
        )}
      </div>

      {/* menu — matches .sight-frame-menu */}
      <div className="sfp-sight-frame-menu">
        {/* back arrow — shown when not on intro */}
        {!isIntro && (
          <button
            className="sfp-back-btn"
            type="button"
            onClick={() => setSelectedSection(-1)}
          >
            <svg
              width="20"
              height="25"
              viewBox="0 0 20 25"
              fill="none"
              xmlns="http://www.w3.org/2000/svg"
              style={{ display: "block" }}
            >
              <defs>
                <linearGradient
                  id="sfpGradient"
                  x1="0%"
                  y1="0%"
                  x2="100%"
                  y2="100%"
                  gradientUnits="userSpaceOnUse"
                >
                  <stop offset="0%" stopColor="rgba(255, 255, 255, 0.2)" />
                  <stop offset="100%" stopColor="rgba(255, 255, 255, 0)" />
                </linearGradient>
                <clipPath id="sfpClip">
                  <rect
                    width="20"
                    height="25"
                    fill="white"
                    transform="translate(12.5 0.5) rotate(90)"
                  />
                </clipPath>
              </defs>
              <g clipPath="url(#sfpClip)">
                <path
                  d="M4.03158 11.0738C4.21879 11.2087 4.34702 11.2766 4.44531 11.3747C6.93048 13.8687 9.41098 16.3665 11.8962 18.8605C12.3408 19.3067 12.5186 19.8207 12.3361 20.4339C12.0281 21.4658 10.7776 21.8393 9.95295 21.1498C9.86309 21.0743 9.78165 20.9894 9.69928 20.9064C6.85279 18.0446 4.00537 15.1817 1.15982 12.3189C0.280876 11.4341 0.281813 10.6456 1.16169 9.75982C4.04 6.86305 6.91457 3.96155 9.80786 1.07986C10.0597 0.828952 10.4144 0.619547 10.7561 0.537482C11.4019 0.382786 12.015 0.72142 12.3193 1.28644C12.6263 1.85334 12.5392 2.56079 12.0806 3.05129C11.7286 3.4286 11.3561 3.78704 10.991 4.15209C8.79601 6.35557 6.60194 8.55904 4.40599 10.7606C4.32362 10.8436 4.22721 10.9106 4.03158 11.0729L4.03158 11.0738Z"
                  fill="url(#sfpGradient)"
                />
              </g>
            </svg>
          </button>
        )}

        {/* article nav buttons — matches .sight-frame-menu-point */}
        {articles.map((article, index) => (
          <button
            key={article.id}
            type="button"
            className={`sfp-sight-frame-menu-point${selectedSection === index ? " active" : ""}`}
            onClick={() => {
              setSelectedSection(index);
              onArticleSelect(index);
            }}
          >
            {article.heading}
          </button>
        ))}
      </div>
    </div>
  );
}
