/* solarengineering.online — production App */
(function () {
  const { Icon, Dashboard, DocViewer, ProjectNameEditor } = window;
  const h = React.createElement;
  const { useState, useEffect, useCallback, useRef } = React;

  const SCREENS = {
    upload: window.ScreenUpload,
    classify: window.ScreenClassify,
    pay: window.ScreenPay,
    validate: window.ScreenValidate,
    engineering: window.ScreenEngineering,
    result: window.ScreenResult,
    sistering: window.ScreenSistering,
    deliver: window.ScreenDeliver,
  };

  // 'quote' step removed — merged into 'pay' (single combined screen)
  const VISIBLE_STEPS = ["upload", "pay", "deliver"];
  const VISIBLE_LABELS = {
    upload: ["Upload", null],
    pay: ["Payment", null],
    deliver: ["Deliver", ""],
  };

  function buildSeq(project) {
    const s = ["upload", "pay", "validate", "engineering", "result"];
    if (project && project.status === "sistering") s.push("sistering");
    s.push("deliver");
    return s;
  }

  function visibleStepFor(stepKey) {
    if (stepKey === "pay" || stepKey === "quote") return "pay";
    if (stepKey === "upload" || stepKey === "classify") return "upload";
    return "deliver";
  }

  function targetForVisibleStep(stepKey) {
    return {
      upload: "upload",
      pay: "pay",
      deliver: "deliver",
    }[stepKey];
  }

  // ─── Auth hook ────────────────────────────────────────────────────────────────
  function useAuth() {
    const [user, setUser] = useState(null);
    const [loading, setLoading] = useState(true);

    useEffect(() => {
      if (window.API.auth.isLoggedIn()) {
        window.API.auth
          .me()
          .then((d) => setUser(d.user || d))
          .catch(() => {
            window.API.auth.setToken(null);
          })
          .finally(() => setLoading(false));
      } else {
        setLoading(false);
      }
    }, []);

    const login = async (email, password) => {
      const d = await window.API.auth.login(email, password);
      setUser(d.user || d);
      return d;
    };

    const logout = async () => {
      await window.API.auth.logout().catch(() => {});
      setUser(null);
    };

    return { user, loading, login, logout, setUser };
  }

  // ─── Projects hook ────────────────────────────────────────────────────────────
  function useProjects(user) {
    const [projects, setProjects] = useState([]);
    const [loading, setLoading] = useState(false);

    const refresh = useCallback(() => {
      if (!user) return;
      setLoading(true);
      window.API.projects
        .list()
        .then((d) => setProjects(Array.isArray(d) ? d : d.projects || []))
        .catch(() => {})
        .finally(() => setLoading(false));
    }, [user]);

    useEffect(() => {
      refresh();
    }, [refresh]);

    return { projects, loading, refresh };
  }

  // ─── Root App ─────────────────────────────────────────────────────────────────
  function App() {
    const { user, loading: authLoading, login, logout, setUser } = useAuth();
    const [view, setView] = useState("onboard"); // onboard | dashboard | flow | profile
    // True when the URL has payment-return params that need async resolution —
    // keeps the loading spinner visible so onboarding never flashes before the
    // correct flow step is set.
    const [resolving, setResolving] = useState(() => {
      const p = new URLSearchParams(window.location.search);
      return !!(p.get("project") && p.get("payment"));
    });
    const [project, setProject] = useState(null);
    const [idx, setIdx] = useState(0);
    const [dark, setDark] = useState(
      () => localStorage.getItem("se_dark") === "1",
    );
    const [docState, setDocState] = useState(null);
    const [creatingProject, setCreatingProject] = useState(false);
    const { projects, loading: projLoading, refresh } = useProjects(user);

    useEffect(() => {
      document.documentElement.classList.toggle("dark", dark);
      localStorage.setItem("se_dark", dark ? "1" : "0");
    }, [dark]);

    // Once auth resolves, route to the right view.
    // If returning from Stripe Checkout, handle payment verification first.
    useEffect(() => {
      if (authLoading) return;

      const params = new URLSearchParams(window.location.search);
      const projectId = params.get("project");
      const payment = params.get("payment");
      const sessionId = params.get("session_id");

      if (user && projectId && payment) {
        window.history.replaceState({}, "", "/");
        window.API.projects
          .get(projectId)
          .then((p) => {
            if (payment === "success" && sessionId) {
              return window.API.projects
                .paymentReturn(projectId, sessionId)
                .then((d) => {
                  const updated = d && d.project ? d.project : p;
                  setProject(updated);
                  const s = buildSeq(updated);
                  setIdx(s.indexOf("validate"));
                  setView("flow");
                  setResolving(false);
                })
                .catch(() => {
                  // Verification failed — land on pay step so user can retry
                  setProject(p);
                  const s = buildSeq(p);
                  setIdx(s.indexOf("pay"));
                  setView("flow");
                  setResolving(false);
                });
            }
            // payment=cancel — return to pay step
            setProject(p);
            const s = buildSeq(p);
            setIdx(s.indexOf("pay"));
            setView("flow");
            setResolving(false);
          })
          .catch(() => {
            setView("dashboard");
            setResolving(false);
          });
        return;
      }

      if (user) setView("dashboard");
      else {
        setView("onboard");
        setResolving(false);
      }
    }, [authLoading, user]);

    const seq = project ? buildSeq(project) : [];
    const stepKey = seq[idx];
    const openDocs = useCallback(
      (p, files) => setDocState({ project: p, files }),
      [],
    );

    // ─── Onboarding complete → dashboard ──────────────────────────────────────────
    const finishOnboarding = async () => {
      try {
        const me = await window.API.auth.me();
        setUser(me.user || me);
        setView("dashboard");
      } catch (err) {
        console.error("onboarding completion failed", err);
      }
    };

    // ─── Resume a project from dashboard ─────────────────────────────────────────
    const resume = (p) => {
      const s = buildSeq(p);
      let j = 0;
      if (p.status === "uploaded" || p.status === "pre_screened")
        j = s.indexOf("upload");
      else if (p.status === "classified" || p.status === "quoted")
        j = s.indexOf("pay");
      else if (p.status === "payment_pending") j = s.indexOf("pay");
      else if (p.status === "paid" || p.status === "validating")
        j = s.indexOf("validate");
      else if (p.status === "in_progress") j = s.indexOf("engineering");
      else if (p.status === "missing_info") j = s.indexOf("upload");
      else if (p.status === "sistering" || p.status === "sistering_pending")
        j = s.indexOf("result");
      else if (p.status === "rejected") j = s.indexOf("upload");
      else if (p.status === "delivered") j = s.indexOf("deliver");
      setProject(p);
      setIdx(Math.max(0, j));
      setView("flow");
    };

    // ─── Start a brand-new project ────────────────────────────────────────────────
    const startNew = async () => {
      if (creatingProject) return;
      setCreatingProject(true);
      try {
        const p = await window.API.projects.create("", "", "", "");
        setProject(p);
        setIdx(0);
        setView("flow");
        refresh();
      } catch (err) {
        console.error("create project failed", err);
      } finally {
        setCreatingProject(false);
      }
    };

    // go object passed to all screen components
    const go = {
      next: () => setIdx((i) => Math.min(i + 1, seq.length - 1)),
      prev: () => setIdx((i) => Math.max(i - 1, 0)),
      dashboard: () => {
        setView("dashboard");
        setProject(null);
        setIdx(0);
        refresh();
      },
      toDeliver: () => setIdx(seq.indexOf("deliver")),
      toQuote: () => setIdx(seq.indexOf("pay")),
      toUpload: () => setIdx(seq.indexOf("upload")),
      updateProject: (p) => setProject(p),
    };

    const Screen = stepKey ? SCREENS[stepKey] : null;

    if (authLoading || resolving) {
      return h(
        "div",
        { style: { display: "grid", placeItems: "center", height: "100vh" } },
        h(Icon, {
          name: "sun",
          size: 32,
          style: {
            color: "var(--accent)",
            animation: "spin 1.5s linear infinite",
          },
        }),
      );
    }

    if (view === "onboard") {
      return h(
        React.Fragment,
        null,
        h(window.Onboarding, { onComplete: finishOnboarding, onLogin: login }),
      );
    }

    const goProfile = () => setView("profile");
    const backFromProfile = () => setView(project ? "flow" : "dashboard");

    return h(
      "div",
      { className: "app" },
      h(Topbar, {
        project: view === "flow" ? project : null,
        user,
        dark,
        onHome: go.dashboard,
        onToggleDark: () => setDark((d) => !d),
        onLogout: logout,
        onProfile: goProfile,
        onRenameProject: (n) => setProject((p) => (p ? { ...p, name: n } : p)),
      }),
      view === "profile"
        ? h(
            "div",
            { className: "app-body no-rail" },
            h(
              "div",
              { className: "canvas" },
              h(window.ProfileSettings, {
                user,
                onUpdate: (updated) => setUser(updated),
                onBack: backFromProfile,
              }),
            ),
          )
        : view === "dashboard"
          ? h(
              "div",
              { className: "app-body no-rail" },
              h(
                "div",
                { className: "canvas" },
                h(Dashboard, {
                  projects,
                  loading: projLoading,
                  empty: projects.length === 0,
                  onNew: startNew,
                  onResume: resume,
                  onOpenProject: (p) =>
                    openDocs(
                      p,
                      p.status === "sistering" ? p.sisterFiles : p.files,
                    ),
                  onRefresh: refresh,
                }),
              ),
            )
          : h(
              "div",
              { className: "app-body" },
              h(Rail, {
                project,
                seq,
                idx,
                active: visibleStepFor(stepKey),
                onRenameProject: (n) =>
                  setProject((p) => (p ? { ...p, name: n } : p)),
              }),
              h(
                "div",
                { className: "canvas" },
                h(
                  "div",
                  {
                    className:
                      "canvas-inner" +
                      (stepKey === "deliver" || stepKey === "result"
                        ? " wide"
                        : ""),
                  },
                  Screen &&
                    h(Screen, {
                      key: stepKey + (project && project.id),
                      project,
                      tweaks: {},
                      go,
                      openDocs,
                    }),
                ),
              ),
            ),
      docState &&
        h(DocViewer, {
          project: docState.project,
          files: docState.files,
          dcrStyle: "bars",
          onClose: () => setDocState(null),
        }),
    );
  }

  // ─── Topbar ───────────────────────────────────────────────────────────────────
  function Topbar({
    project,
    user,
    dark,
    onHome,
    onToggleDark,
    onLogout,
    onProfile,
    onRenameProject,
  }) {
    const [menuOpen, setMenuOpen] = useState(false);
    const menuRef = useRef(null);
    const projectLocation = project
      ? project.city || project.address || ""
      : "";
    const initials = user
      ? (
          (user.first_name || "").slice(0, 1) +
          (user.last_name || "").slice(0, 1)
        ).toUpperCase() || (user.email || "U").slice(0, 2).toUpperCase()
      : "??";
    const fullName = user
      ? [user.first_name, user.last_name].filter(Boolean).join(" ")
      : "";

    useEffect(() => {
      const handler = (e) => {
        if (menuRef.current && !menuRef.current.contains(e.target))
          setMenuOpen(false);
      };
      document.addEventListener("mousedown", handler);
      return () => document.removeEventListener("mousedown", handler);
    }, []);

    return h(
      "div",
      { className: "topbar" },
      h(
        "div",
        {
          className: "brand",
          onClick: onHome,
          style: { cursor: "pointer", lineHeight: 0 },
        },
        h("img", {
          src: "/static/solarengineering-logo.svg",
          alt: "solarengineering.online",
          style: { height: 30, width: "auto", display: "block" },
        }),
      ),
      project &&
        h(
          "div",
          { className: "topbar-ctx" },
          h(Icon, { name: "map-pin", size: 13 }),
          h(ProjectNameEditor, {
            projectId: project.id,
            name: project.name,
            onSaved: onRenameProject,
            textStyle: { fontSize: "inherit", fontWeight: "inherit" },
          }),
          projectLocation &&
            h("span", { style: { color: "var(--border-strong)" } }, "·"),
          projectLocation && h("span", { className: "num" }, projectLocation),
        ),
      h("div", { className: "topbar-spacer" }),
      h(
        "button",
        {
          className: "topbar-btn",
          onClick: onToggleDark,
          title: "Toggle theme",
        },
        h(Icon, { name: dark ? "sun" : "moon", size: 16 }),
      ),
      h(
        "button",
        { className: "topbar-btn", onClick: onHome },
        h(Icon, { name: "folder", size: 15 }),
        "Projects",
      ),
      h(
        "div",
        { style: { position: "relative" }, ref: menuRef },
        h(
          "div",
          {
            className: "avatar",
            title: user ? user.email : "",
            style: { cursor: "pointer" },
            onClick: () => setMenuOpen((o) => !o),
          },
          initials,
        ),
        menuOpen &&
          h(
            "div",
            { className: "avatar-menu" },
            h(
              "div",
              { className: "avatar-menu-header" },
              h(
                "div",
                {
                  style: { fontWeight: 600, fontSize: 14, color: "var(--fg)" },
                },
                fullName || user?.email,
              ),
              fullName &&
                h(
                  "div",
                  {
                    style: {
                      fontSize: 12,
                      color: "var(--fg-subtle)",
                      marginTop: 2,
                    },
                  },
                  user?.email,
                ),
            ),
            h("div", { className: "avatar-menu-sep" }),
            h(
              "div",
              {
                className: "avatar-menu-item",
                onClick: () => {
                  onProfile();
                  setMenuOpen(false);
                },
              },
              h(Icon, { name: "user", size: 14 }),
              "Profile & Settings",
            ),
            h("div", { className: "avatar-menu-sep" }),
            h(
              "div",
              {
                className: "avatar-menu-item avatar-menu-item-danger",
                onClick: () => {
                  onLogout();
                  setMenuOpen(false);
                },
              },
              h(Icon, { name: "log-out", size: 14 }),
              "Sign out",
            ),
          ),
      ),
    );
  }

  // ─── Pipeline Rail ────────────────────────────────────────────────────────────
  function Rail({ project, seq, idx, active, onRenameProject }) {
    if (!project) return null;
    const activeIndex = Math.max(0, VISIBLE_STEPS.indexOf(active));
    return h(
      "div",
      { className: "rail" },
      h(
        "div",
        { className: "rail-head" },
        h(
          "div",
          { className: "rail-proj" },
          h(ProjectNameEditor, {
            projectId: project.id,
            name: project.name,
            onSaved: onRenameProject,
            textStyle: { fontWeight: "inherit", fontSize: "inherit" },
          }),
        ),
      ),
      h(
        "div",
        { className: "rail-group-label" },
        h("div", { className: "eyebrow" }, "Pipeline"),
      ),
      h(
        "ul",
        { className: "steps" },
        VISIBLE_STEPS.map((k, i) => {
          let state =
            i < activeIndex
              ? "done"
              : i === activeIndex
                ? "current"
                : "pending";
          if (i === activeIndex) {
            if (
              (project.truss || project.status === "rejected") &&
              k === "upload"
            )
              state = "blocked current";
            if (
              project.status === "missing_info" &&
              (k === "upload" || k === "deliver")
            )
              state = "blocked current";
            if (
              (project.status === "sistering" ||
                project.status === "sistering_pending") &&
              k === "deliver"
            )
              state = "exception current";
          }
          const [label, sub] = VISIBLE_LABELS[k];
          const done = i < activeIndex;
          void seq;
          void idx;
          return h(
            "li",
            {
              key: k,
              className: "step " + state,
              style: { cursor: "default" },
            },
            h(
              "div",
              { className: "step-node" },
              h(
                "div",
                { className: "step-dot" },
                done ? h(Icon, { name: "check", size: 12 }) : i + 1,
              ),
              h("div", { className: "step-line" }),
            ),
            h(
              "div",
              { className: "step-label" },
              label,
              sub && h("small", null, sub),
            ),
          );
        }),
      ),
      h(
        "div",
        { className: "rail-foot" },
        h(
          "div",
          {
            style: { fontSize: 11, color: "var(--fg-subtle)", lineHeight: 1.5 },
          },
          "© 2026 SolarEngineering. All rights reserved.",
          h("br"),
          h(
            "a",
            {
              href: "/privacy",
              target: "_blank",
              rel: "noopener noreferrer",
              style: { color: "inherit" },
            },
            "Privacy Policy",
          ),
          " | ",
          h(
            "a",
            {
              href: "/terms",
              target: "_blank",
              rel: "noopener noreferrer",
              style: { color: "inherit" },
            },
            "Terms & Conditions",
          ),
        ),
      ),
    );
  }

  window.SolarEngApp = App;
})();
