import { useEffect, useState } from "react";

interface TextState {
  showing: boolean;
  title: string;
}

interface ImagePopupState {
  showing: boolean;
  image_url: string;
  caption: string;
}

interface DisplayOptions {
  font_size: number;
  text_color: string;
}

interface DataCardConfig {
  url: string;
  refresh_interval: number;
  display_options: DisplayOptions;
  take?: string;
  additional_headers?: Record<string, string>;
}

interface DataCard {
  id: string;
  type: "custom_json";
  name: string;
  config: DataCardConfig;
}

// ─── Path evaluator for "$out.foo.bar[0].baz" ────────────────────────────────

function evaluatePath(data: unknown, path: string): unknown {
  if (!path || !path.startsWith("$out")) return data;
  const expr = path.slice(4); // strip "$out"
  const tokens: string[] = [];
  const regex = /\.([a-zA-Z_][a-zA-Z0-9_]*)|\[(\d+)\]/g;
  let match: RegExpExecArray | null;
  while ((match = regex.exec(expr)) !== null) {
    tokens.push(match[1] ?? match[2]);
  }
  let current: unknown = data;
  for (const token of tokens) {
    if (current == null) return null;
    const idx = parseInt(token, 10);
    if (!isNaN(idx) && Array.isArray(current)) {
      current = current[idx];
    } else {
      current = (current as Record<string, unknown>)[token];
    }
  }
  return current;
}

// ─── Data Card Widget ─────────────────────────────────────────────────────────

function DataCardWidget({ card }: { card: DataCard }) {
  const [value, setValue] = useState<string>("…");
  const [lastUpdated, setLastUpdated] = useState<Date | null>(null);
  const [error, setError] = useState<string | null>(null);

  useEffect(() => {
    const fetchData = () => {
      const headers: Record<string, string> = {
        Accept: "application/json",
        ...(card.config.additional_headers ?? {}),
      };
      fetch(card.config.url, { headers })
        .then((r) => r.json())
        .then((data) => {
          const result = card.config.take
            ? evaluatePath(data, card.config.take)
            : data;
          const display =
            result === null || result === undefined
              ? "(null)"
              : typeof result === "object"
                ? JSON.stringify(result, null, 2)
                : String(result);
          setValue(display);
          setLastUpdated(new Date());
          setError(null);
        })
        .catch((err) => {
          setError(String(err));
        });
    };

    fetchData();
    const ms = Math.max(5000, (card.config.refresh_interval ?? 60) * 1000);
    const interval = setInterval(fetchData, ms);
    return () => clearInterval(interval);
  }, [card.id, card.config.url, card.config.refresh_interval, card.config.take]);

  const fontSize = card.config.display_options?.font_size ?? 16;
  const textColor = card.config.display_options?.text_color ?? "#ffffff";

  return (
    <div className="flex flex-col gap-1 bg-black/40 backdrop-blur-sm rounded-2xl border border-white/10 px-5 py-4 min-w-[160px] max-w-[320px]">
      <span className="text-gray-400 text-xs font-semibold uppercase tracking-wider">
        {card.name}
      </span>
      {error ? (
        <span className="text-red-400 text-sm break-all">⚠ {error}</span>
      ) : (
        <span
          className="font-mono break-all whitespace-pre-wrap leading-snug"
          style={{ fontSize, color: textColor }}
        >
          {value}
        </span>
      )}
      {lastUpdated && (
        <span className="text-gray-600 text-xs mt-1">
          {lastUpdated.toLocaleTimeString()}
        </span>
      )}
    </div>
  );
}

function App() {
  const [screenStatus, setScreenStatus] = useState<
    "notfullscreen" | "fullscreen"
  >("notfullscreen");
  const [textState, setTextState] = useState<TextState>({ showing: false, title: "" });
  const [imagePopup, setImagePopup] = useState<ImagePopupState>({ showing: false, image_url: "", caption: "" });
  const [dataCards, setDataCards] = useState<DataCard[]>([]);

  useEffect(() => {
    const handleFullscreenChange = () => {
      if (!document.fullscreenElement) {
        setScreenStatus("notfullscreen");
      } else {
        setScreenStatus("fullscreen");
      }
    };

    document.addEventListener("fullscreenchange", handleFullscreenChange);

    return () => {
      document.removeEventListener("fullscreenchange", handleFullscreenChange);
    };
  }, []);

  useEffect(() => {
    if (screenStatus === "fullscreen") {
      const handlePullState = () => {
        fetch(
          "https://shsf-api.reversed.dev/api/exec/15/1c44d8b5-4065-4a54-b259-748561021329/pull_full",
        )
          .then((response) => response.json())
          .then((data) => {
            const state = data.state ?? {};
            setTextState(state.text ?? { showing: false, title: "" });
            setImagePopup(state.image_popup ?? { showing: false, image_url: "", caption: "" });
            setDataCards(state.data_cards ?? []);
          })
          .catch((error) => {
            console.error("Error pulling state:", error);
          });
      };

      handlePullState();
      const interval = setInterval(handlePullState, 5000);

      return () => clearInterval(interval);
    }
  }, [screenStatus]);

  return (
    <>
      {screenStatus === "notfullscreen" ? (
        <div className="flex flex-col items-center gap-8 px-8 text-center">
          <div className="flex flex-col items-center gap-2">
            <div className="w-16 h-16 rounded-2xl bg-gray-800 border border-gray-700 flex items-center justify-center mb-2">
              <svg
                xmlns="http://www.w3.org/2000/svg"
                className="w-8 h-8 text-gray-400"
                fill="none"
                viewBox="0 0 24 24"
                stroke="currentColor"
                strokeWidth={1.5}
              >
                <path
                  strokeLinecap="round"
                  strokeLinejoin="round"
                  d="M6 8V6a2 2 0 012-2h8a2 2 0 012 2v2M6 16v2a2 2 0 002 2h8a2 2 0 002-2v-2M3 12h18"
                />
              </svg>
            </div>
            <h1 className="text-3xl font-semibold tracking-tight text-white">
              TV View
            </h1>
            <p className="text-gray-500 text-sm max-w-xs">
              Enter fullscreen mode to start displaying content.
            </p>
          </div>

          <button
            onClick={() => document.documentElement.requestFullscreen()}
            className="group flex items-center gap-2 bg-white text-gray-900 font-medium px-6 py-3 rounded-xl hover:bg-gray-200 active:scale-95 transition-all duration-150 cursor-pointer"
          >
            <svg
              xmlns="http://www.w3.org/2000/svg"
              className="w-4 h-4"
              fill="none"
              viewBox="0 0 24 24"
              stroke="currentColor"
              strokeWidth={2}
            >
              <path
                strokeLinecap="round"
                strokeLinejoin="round"
                d="M4 8V4m0 0h4M4 4l5 5m11-5h-4m4 0v4m0-4l-5 5M4 16v4m0 0h4m-4 0l5-5m11 5l-5-5m5 5v-4m0 4h-4"
              />
            </svg>
            Go Fullscreen
          </button>
        </div>
      ) : (
        <div className="w-screen h-screen relative">
          {/* Text popup modal */}
          {textState.showing && (
            <div className="absolute inset-0 z-10 flex items-center justify-center bg-black/70 backdrop-blur-sm">
              <div className="bg-gray-900 border border-gray-700 rounded-3xl px-16 py-12 shadow-2xl max-w-3xl w-full mx-8">
                <h1 className="text-6xl font-bold tracking-tight text-white text-center">
                  {textState.title}
                </h1>
              </div>
            </div>
          )}

          {/* Image popup modal */}
          {imagePopup.showing && imagePopup.image_url && (
            <div className="absolute inset-0 z-20 flex items-center justify-center bg-black/75 backdrop-blur-sm p-12">
              <div className="flex flex-col items-center gap-5 p-6 bg-gray-950/80 rounded-3xl border border-white/10 shadow-2xl max-w-[82vw]">
                {imagePopup.caption && (
                  <h2 className="text-4xl font-bold text-white tracking-tight text-center">
                    {imagePopup.caption}
                  </h2>
                )}
                <img
                  src={imagePopup.image_url}
                  alt="TV display"
                  className="max-w-full max-h-[72vh] rounded-2xl object-contain shadow-xl"
                  style={{ display: "block" }}
                />
              </div>
            </div>
          )}

          {/* Background idle state */}
          {!textState.showing && !imagePopup.showing && dataCards.length === 0 && (
            <div className="flex items-center justify-center w-full h-full">
              <p className="text-gray-600 text-lg">
                Waiting for content
                <span className="dot-1">.</span>
                <span className="dot-2">.</span>
                <span className="dot-3">.</span>
              </p>
            </div>
          )}

          {/* Data cards — persistent widgets at the bottom */}
          {dataCards.length > 0 && (
            <div className="absolute bottom-0 left-0 right-0 z-0 flex flex-row flex-wrap gap-4 p-6 items-end">
              {dataCards.map((card) => (
                <DataCardWidget key={card.id} card={card} />
              ))}
            </div>
          )}
        </div>
      )}
    </>
  );
}

export default App;
