function LoadingState({ title = "Conectando", body = "Cargando datos reales..." }) {
  return (
    <div
      style={{
        height: "100%",
        display: "flex",
        flexDirection: "column",
        alignItems: "center",
        justifyContent: "center",
        gap: 12,
        padding: 24,
        textAlign: "center"
      }}
    >
      <div
        className="serif"
        style={{
          fontSize: 34,
          lineHeight: 1,
          letterSpacing: "-0.02em"
        }}
      >
        {title}
      </div>
      <div
        style={{
          width: 42,
          height: 42,
          borderRadius: "50%",
          border: "2px solid rgba(255,255,255,0.14)",
          borderTopColor: "#fff",
          animation: "ainaSpin 1s linear infinite"
        }}
      />
      <div
        style={{
          fontSize: 13,
          lineHeight: 1.5,
          color: "rgba(255,255,255,0.6)",
          maxWidth: 220
        }}
      >
        {body}
      </div>
      <style>{`
        @keyframes ainaSpin {
          from { transform: rotate(0deg); }
          to { transform: rotate(360deg); }
        }
      `}</style>
    </div>
  );
}

const App = () => {
  const [viewer, setViewer] = React.useState(null);
  const [authToken, setAuthToken] = React.useState(
    readPreviewStorage(AINA_PREVIEW_AUTH_KEY, "")
  );
  const [authProfiles, setAuthProfiles] = React.useState([]);
  const [snapshot, setSnapshot] = React.useState(null);
  const [viewedProfileId, setViewedProfileId] = React.useState(
    readPreviewStorage(AINA_PREVIEW_VIEW_KEY, "")
  );
  const [tab, setTab] = React.useState("home");
  const [overlay, setOverlay] = React.useState(null);
  const [transitioning, setTransitioning] = React.useState(false);
  const [busy, setBusy] = React.useState(true);
  const [errorMessage, setErrorMessage] = React.useState("");
  const [statusMessage, setStatusMessage] = React.useState("");

  const loadAuthProfiles = React.useCallback(async () => {
    const data = await previewApi("/api/auth/options");
    setAuthProfiles(data.profiles || []);
    return data.profiles || [];
  }, []);

  const loadDashboardWithToken = React.useCallback(async (token, selectedProfileId, viewerProfileId) => {
    const safeSelectedProfileId =
      selectedProfileId ||
      readPreviewStorage(AINA_PREVIEW_VIEW_KEY, "") ||
      viewerProfileId ||
      "";
    const query = safeSelectedProfileId
      ? `?selectedProfileId=${encodeURIComponent(safeSelectedProfileId)}`
      : "";
    const nextSnapshot = await previewApi(`/api/dashboard/today${query}`, {
      token
    });
    setSnapshot(nextSnapshot);
    setViewedProfileId(nextSnapshot.selectedProfileId || viewerProfileId || "");
    writePreviewStorage(
      AINA_PREVIEW_VIEW_KEY,
      nextSnapshot.selectedProfileId || viewerProfileId || ""
    );
    return nextSnapshot;
  }, []);

  const runTask = React.useCallback(async (task, options = {}) => {
    setBusy(true);
    setErrorMessage("");
    try {
      const result = await task();
      if (options.successMessage) {
        setStatusMessage(options.successMessage);
      }
      return result;
    } catch (error) {
      setErrorMessage(error.message);
      throw error;
    } finally {
      setBusy(false);
    }
  }, []);

  React.useEffect(() => {
    const timeoutId = statusMessage
      ? window.setTimeout(() => setStatusMessage(""), 2600)
      : 0;

    return () => {
      if (timeoutId) {
        window.clearTimeout(timeoutId);
      }
    };
  }, [statusMessage]);

  React.useEffect(() => {
    let cancelled = false;

    const bootstrap = async () => {
      setBusy(true);
      try {
        await loadAuthProfiles();
        if (!authToken) {
          if (!cancelled) {
            setViewer(null);
            setSnapshot(null);
          }
          return;
        }

        const session = await previewApi("/api/auth/session", {
          token: authToken
        });
        if (cancelled) {
          return;
        }

        setViewer(session.viewer);
        if (session.profiles?.length) {
          setAuthProfiles(session.profiles);
        }

        await loadDashboardWithToken(
          authToken,
          viewedProfileId || session.viewer.profileId,
          session.viewer.profileId
        );
      } catch (_error) {
        if (!cancelled) {
          writePreviewStorage(AINA_PREVIEW_AUTH_KEY, "");
          writePreviewStorage(AINA_PREVIEW_VIEW_KEY, "");
          setAuthToken("");
          setViewer(null);
          setSnapshot(null);
        }
      } finally {
        if (!cancelled) {
          setBusy(false);
        }
      }
    };

    bootstrap();

    return () => {
      cancelled = true;
    };
  }, [authToken, loadAuthProfiles, loadDashboardWithToken, viewedProfileId]);

  const login = React.useCallback(
    async (profileId, password) =>
      runTask(async () => {
        const data = await previewApi("/api/auth/login", {
          method: "POST",
          body: {
            profileId,
            password
          }
        });

        setAuthToken(data.token);
        writePreviewStorage(AINA_PREVIEW_AUTH_KEY, data.token);
        setViewer(data.viewer);
        setSnapshot(null);
        setOverlay(null);
        setTab("home");

        if (data.profiles?.length) {
          setAuthProfiles(data.profiles);
        }

        await loadDashboardWithToken(
          data.token,
          data.viewer.profileId,
          data.viewer.profileId
        );

        return data;
      }),
    [loadDashboardWithToken, runTask]
  );

  const logout = React.useCallback(() => {
    writePreviewStorage(AINA_PREVIEW_AUTH_KEY, "");
    writePreviewStorage(AINA_PREVIEW_VIEW_KEY, "");
    setAuthToken("");
    setViewer(null);
    setSnapshot(null);
    setViewedProfileId("");
    setOverlay(null);
    setTab("home");
    setErrorMessage("");
    setStatusMessage("");
  }, []);

  const refresh = React.useCallback(
    async (selectedProfileId = "") => {
      if (!authToken || !viewer) {
        return null;
      }

      return runTask(() =>
        loadDashboardWithToken(
          authToken,
          selectedProfileId || snapshot?.selectedProfileId || viewer.profileId,
          viewer.profileId
        )
      );
    },
    [authToken, viewer, snapshot, runTask, loadDashboardWithToken]
  );

  const selectProfile = React.useCallback(
    async (profileId) => {
      if (!authToken || !viewer || !profileId) {
        return null;
      }

      return runTask(() =>
        loadDashboardWithToken(authToken, profileId, viewer.profileId)
      );
    },
    [authToken, viewer, runTask, loadDashboardWithToken]
  );

  const mutate = React.useCallback(
    async (path, requestOptions = {}, messages = {}) => {
      if (!authToken || !viewer) {
        throw new Error("Sesion caducada.");
      }

      return runTask(
        async () => {
          const result = await previewApi(path, {
            ...requestOptions,
            token: authToken
          });

          await loadDashboardWithToken(
            authToken,
            snapshot?.selectedProfileId || viewer.profileId,
            viewer.profileId
          );

          return result;
        },
        {
          successMessage: messages.successMessage || ""
        }
      );
    },
    [authToken, viewer, snapshot, runTask, loadDashboardWithToken]
  );

  const openOverlay = React.useCallback(
    async (nextOverlay) => {
      if (!viewer) {
        return;
      }

      if (
        (nextOverlay === "checkin" || nextOverlay === "night") &&
        snapshot?.selectedProfileId &&
        snapshot.selectedProfileId !== viewer.profileId
      ) {
        await selectProfile(viewer.profileId);
      }

      setOverlay(nextOverlay);
    },
    [viewer, snapshot, selectProfile]
  );

  const changeTab = React.useCallback(
    async (nextTab) => {
      if (!viewer || nextTab === tab) {
        return;
      }

      setTransitioning(true);
      if (nextTab === "me" && snapshot?.selectedProfileId !== viewer.profileId) {
        await selectProfile(viewer.profileId);
      }

      window.setTimeout(() => {
        setTab(nextTab);
        setTransitioning(false);
      }, 120);
    },
    [viewer, tab, snapshot, selectProfile]
  );

  const selectedProfile = snapshot?.selectedProfile || null;
  const partnerProfile = viewer ? getPartnerProfile(snapshot, viewer.profileId) : null;

  const contextValue = {
    viewer,
    authProfiles,
    authToken,
    snapshot,
    selectedProfile,
    partnerProfile,
    viewedProfileId,
    busy,
    errorMessage,
    statusMessage,
    login,
    logout,
    refresh,
    selectProfile,
    saveDay: (body) =>
      mutate(
        "/api/day",
        {
          method: "PUT",
          body
        },
        {
          successMessage: "Check-in guardado."
        }
      ),
    addHabit: (title, category) =>
      mutate(
        "/api/habits",
        {
          method: "POST",
          body: { title, category }
        },
        {
          successMessage: "Habito guardado."
        }
      ),
    toggleHabit: (habitId) =>
      mutate(
        `/api/habits/${habitId}/toggle`,
        {
          method: "PATCH"
        },
        {
          successMessage: "Habito actualizado."
        }
      ),
    deleteHabit: (habitId) =>
      mutate(
        `/api/habits/${habitId}`,
        {
          method: "DELETE"
        },
        {
          successMessage: "Habito borrado."
        }
      ),
    addTask: (title) =>
      mutate(
        "/api/tasks",
        {
          method: "POST",
          body: { title }
        },
        {
          successMessage: "Tarea guardada."
        }
      ),
    toggleTask: (taskId) =>
      mutate(
        `/api/tasks/${taskId}/toggle`,
        {
          method: "PATCH"
        },
        {
          successMessage: "Tarea actualizada."
        }
      ),
    deleteTask: (taskId) =>
      mutate(
        `/api/tasks/${taskId}`,
        {
          method: "DELETE"
        },
        {
          successMessage: "Tarea borrada."
        }
      ),
    addComment: (body) =>
      mutate(
        "/api/comments",
        {
          method: "POST",
          body: { body }
        },
        {
          successMessage: "Comentario enviado."
        }
      ),
    reactComment: (commentId, type) =>
      mutate(`/api/comments/${commentId}/reactions`, {
        method: "POST",
        body: { type }
      }),
    updateCoupleGoal: (body) =>
      mutate(
        "/api/couple/goal",
        {
          method: "PUT",
          body
        },
        {
          successMessage: "Meta conjunta guardada."
        }
      ),
    updateCoupleDailyClose: (body) =>
      mutate(
        "/api/couple/daily-close",
        {
          method: "PUT",
          body
        },
        {
          successMessage: "Cierre conjunto guardado."
        }
      ),
    updateWeeklyGoal: (body) =>
      mutate(
        "/api/weekly-goal",
        {
          method: "PUT",
          body
        },
        {
          successMessage: "Objetivo semanal guardado."
        }
      ),
    closeWeeklyGoal: (body) =>
      mutate(
        "/api/weekly-goal/close",
        {
          method: "POST",
          body
        },
        {
          successMessage: "Semana cerrada."
        }
      ),
    openGoogleConnect: async () =>
      runTask(async () => {
        const data = await previewApi("/api/google/connect-url", {
          token: authToken
        });
        window.location.href = data.url;
        return data;
      }),
    disconnectGoogle: () =>
      mutate(
        "/api/google/disconnect",
        {
          method: "POST"
        },
        {
          successMessage: "Google Calendar desconectado."
        }
      )
  };

  const screens = {
    home: <HomeScreen onOpenDiagram={() => openOverlay("diagram")} onOpenNight={() => openOverlay("night")} />,
    couple: <CoupleScreen />,
    timeline: <TimelineScreen />,
    cal: <CalendarScreen />,
    me: (
      <ProfileScreen
        onLogout={logout}
        onViewPartner={() => {
          if (!partnerProfile) {
            return;
          }

          selectProfile(partnerProfile.id).then(() => {
            setTab("home");
          });
        }}
      />
    )
  };

  const infoFor = {
    home: {
      name: "Hoy",
      desc: "Home conectada a tu base real: score, racha conjunta, highlights, habitos, tareas y agenda del perfil seleccionado.",
      meta: 'Pulsa "Diagrama de la paz" para abrir el flujo. El icono de campana abre el resumen nocturno real.'
    },
    couple: {
      name: "Pareja",
      desc: "Meta comun, cierre del dia y metricas compartidas leyendo y escribiendo ya sobre la base real.",
      meta: "El historico semanal sale del backend y se actualiza al guardar cambios."
    },
    timeline: {
      name: "Timeline",
      desc: "Actividad compartida y comentarios reales. Las reacciones escriben en la base y vuelven al feed.",
      meta: "Todo sale de /api/dashboard/today y de los endpoints de comentarios."
    },
    cal: {
      name: "Mes",
      desc: "Heatmap mensual real del perfil seleccionado, con detalle por dia desde la base de datos.",
      meta: "Toca cualquier dia para ver foco, mood, habitos y tareas de esa fecha."
    },
    me: {
      name: "Yo",
      desc: "Tu perfil real: objetivo semanal, estado actual y accesos a integraciones y cierre de sesion.",
      meta: "Solo tu puedes editar tu perfil; la pareja lo ve en modo lectura."
    }
  };

  React.useEffect(() => {
    const rail = document.getElementById("rail");
    const info = document.getElementById("info");
    if (!rail || !info) {
      return;
    }

    const activeId = !viewer ? "login" : overlay || tab;
    rail.innerHTML = "";

    const screenLabel = document.createElement("div");
    screenLabel.className = "label";
    screenLabel.textContent = "Pantallas";
    rail.appendChild(screenLabel);

    [
      ["Login", "login"],
      ["Hoy", "home"],
      ["Pareja", "couple"],
      ["Timeline", "timeline"],
      ["Mes", "cal"],
      ["Yo", "me"]
    ].forEach(([label, id]) => {
      const button = document.createElement("button");
      button.textContent = label;
      if (activeId === id) {
        button.classList.add("active");
      }
      button.onclick = () => {
        if (id === "login") {
          logout();
          return;
        }

        if (!viewer) {
          setErrorMessage("Entra primero para abrir el diseno conectado.");
          return;
        }

        setOverlay(null);
        changeTab(id).catch(() => null);
      };
      rail.appendChild(button);
    });

    const overlayLabel = document.createElement("div");
    overlayLabel.className = "label";
    overlayLabel.textContent = "Modales";
    rail.appendChild(overlayLabel);

    [
      ["Check-in diario", "checkin"],
      ["Resumen nocturno", "night"],
      ["Diagrama de la paz", "diagram"]
    ].forEach(([label, id]) => {
      const button = document.createElement("button");
      button.textContent = label;
      if (activeId === id) {
        button.classList.add("active");
      }
      button.onclick = () => {
        if (!viewer) {
          setErrorMessage("Entra primero para abrir el diseno conectado.");
          return;
        }

        openOverlay(id).catch(() => null);
      };
      rail.appendChild(button);
    });

    if (!viewer) {
      info.innerHTML = `
        <div class="name serif">Aina</div>
        <div class="desc">Preview conectado a la app real. Es una web app con look de iPhone, pero ya lee y escribe en la base de datos del dashboard.</div>
        <div class="meta">Estado<span>${busy ? "Cargando perfiles..." : "Elige un perfil real para entrar"}</span></div>
      `;
      return;
    }

    const infoBlock = overlay
      ? {
          checkin: {
            name: "Check-in",
            desc: "Guarda foco, gratitud, diario y mood en tu dia real.",
            meta: "Al terminar escribe sobre /api/day y recarga el snapshot."
          },
          night: {
            name: "Noche",
            desc: "Resumen nocturno real con score, racha y pendientes de los dos.",
            meta: "Sale de snapshot.nightly."
          },
          diagram: {
            name: "Diagrama",
            desc: "El diagrama sigue siendo visual, pero lo abres dentro de la app ya conectada.",
            meta: "Zoom y cierre sin salir del preview."
          }
        }[overlay]
      : infoFor[tab];

    info.innerHTML = `
      <div class="name serif">${infoBlock.name}</div>
      <div class="desc">${infoBlock.desc}</div>
      <div class="meta">Detalle<span>${infoBlock.meta}</span></div>
    `;
  }, [viewer, overlay, tab, busy, logout, changeTab, openOverlay]);

  const needsBlockingLoader = busy && authToken && !snapshot;

  return (
    <AinaAppContext.Provider value={contextValue}>
      <IOSDevice dark={true}>
        <div
          style={{
            position: "absolute",
            inset: 0,
            background: "transparent",
            overflow: "hidden"
          }}
        >
          <div
            style={{
              position: "absolute",
              inset: 0,
              background: `
                radial-gradient(50% 45% at 25% 25%, oklch(0.55 0.18 350 / 0.45), transparent 60%),
                radial-gradient(45% 40% at 80% 20%, oklch(0.65 0.15 50 / 0.35), transparent 60%),
                radial-gradient(55% 50% at 75% 80%, oklch(0.35 0.16 280 / 0.55), transparent 60%),
                radial-gradient(45% 40% at 15% 80%, oklch(0.45 0.14 240 / 0.4), transparent 60%),
                linear-gradient(180deg, #160a26 0%, #0a0612 100%)
              `,
              animation: "phoneAurora 22s ease-in-out infinite alternate",
              filter: "blur(0.5px)"
            }}
          />
          <div
            style={{
              position: "absolute",
              inset: 0,
              background:
                "url(\"data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='180' height='180'><filter id='n'><feTurbulence baseFrequency='0.9'/><feColorMatrix values='0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0.04 0'/></filter><rect width='180' height='180' filter='url(%23n)'/></svg>\")",
              opacity: 0.7,
              mixBlendMode: "overlay",
              pointerEvents: "none"
            }}
          />

          {needsBlockingLoader ? (
            <LoadingState />
          ) : (
            <div
              style={{
                position: "absolute",
                inset: 0,
                opacity: transitioning ? 0 : 1,
                transition: "opacity 0.18s ease"
              }}
            >
              {!viewer ? (
                <LoginScreen />
              ) : (
                <>
                  {screens[tab]}
                  <TabBar active={tab} onChange={(nextTab) => changeTab(nextTab).catch(() => null)} />
                </>
              )}
            </div>
          )}

          {viewer && tab === "home" && !overlay && (
            <button
              onClick={() => openOverlay("checkin").catch(() => null)}
              style={{
                position: "absolute",
                bottom: 86,
                right: 18,
                zIndex: 50,
                width: 56,
                height: 56,
                borderRadius: 28,
                background: "linear-gradient(135deg, #fff, oklch(0.92 0.06 30))",
                border: "none",
                color: "#0a0612",
                cursor: "pointer",
                boxShadow:
                  "0 8px 24px rgba(0,0,0,0.4), 0 1px 0 rgba(255,255,255,0.6) inset",
                display: "flex",
                alignItems: "center",
                justifyContent: "center",
                fontSize: 22
              }}
            >
              <I.Sparkle size={24} color="#0a0612" />
            </button>
          )}

          {overlay === "checkin" && <CheckinScreen onClose={() => setOverlay(null)} />}
          {overlay === "night" && <NightScreen onClose={() => setOverlay(null)} />}
          {overlay === "diagram" && <DiagramScreen onClose={() => setOverlay(null)} />}

          {(errorMessage || statusMessage) && (
            <div
              style={{
                position: "absolute",
                left: 16,
                right: 16,
                bottom: viewer ? 82 : 24,
                zIndex: 80,
                padding: "12px 14px",
                borderRadius: 18,
                background: errorMessage
                  ? "rgba(140, 54, 54, 0.82)"
                  : "rgba(255,255,255,0.12)",
                border: "0.5px solid rgba(255,255,255,0.18)",
                backdropFilter: "blur(24px)",
                WebkitBackdropFilter: "blur(24px)",
                color: "#fff",
                fontSize: 12,
                lineHeight: 1.45,
                textAlign: "center"
              }}
            >
              {errorMessage || statusMessage}
            </div>
          )}

          <style>{`
            @keyframes phoneAurora {
              0% { transform: translate(0,0) scale(1); }
              50% { transform: translate(-2%, 1%) scale(1.04); }
              100% { transform: translate(1%, -2%) scale(1.02); }
            }
          `}</style>
        </div>
      </IOSDevice>
    </AinaAppContext.Provider>
  );
};

const mount = document.getElementById("phone-mount");
ReactDOM.createRoot(mount).render(<App />);
