/* global React, ReactDOM */
// Bike-Konfigurator — App-Root mit Auth, State, Tweaks, Persistence

const { useState, useEffect, useMemo, useCallback, useRef } = React;
const { TweaksPanel, useTweaks, TweakSection, TweakRadio, TweakColor, TweakButton } = window.Tweaks || {};
const { StudioLayout, EditorialLayout, GarageLayout } = window.BikeLayouts;
const { ComponentDrawer, GarageDrawer, UpgradeModal } = window.BikeUI;
const { CompareView } = window.BikeAdvanced;
const { SLOT_TO_POOL } = window.BikeFmt;
const { AuthScreen } = window.BikeAuth;

// ── Default profile ────────────────────────────────────────────────────────────
const DEFAULT_PROFILE = {
  weight: 92,
  height: 181,
  bike_type: "analog",
  skill_level: "intermediate",
  riding_style: "playful",
  terrain: "trail",
  budget: 3000
};

const TWEAK_DEFAULTS = /*EDITMODE-BEGIN*/{
  "layout": "studio",
  "accent": "#da291c",
  "accentName": "Rosso Corsa"
}/*EDITMODE-END*/;

const ACCENT_PALETTE = [
  { name: "Rosso Corsa", hex: "#da291c" },
  { name: "Hypersail",   hex: "#f6e500" },
  { name: "Mono",        hex: "#ffffff" },
  { name: "Electric",   hex: "#00bcd4" }
];

// ── Auth helpers ───────────────────────────────────────────────────────────────
function getStoredAuth() {
  try {
    const token = localStorage.getItem("bf_token");
    const user  = JSON.parse(localStorage.getItem("bf_user") || "null");
    return token && user ? { token, user } : null;
  } catch { return null; }
}

function authHeaders(token) {
  return { "Authorization": `Bearer ${token}`, "Content-Type": "application/json" };
}

// ── App root ───────────────────────────────────────────────────────────────────
function App({ frames, components }) {
  // Auth
  const [auth, setAuth] = useState(getStoredAuth);
  const [plan, setPlan] = useState("free");
  const [upgradeOpen, setUpgradeOpen] = useState(false);

  const handleAuth = (user, token) => setAuth({ user, token });

  const handleLogout = () => {
    localStorage.removeItem("bf_token");
    localStorage.removeItem("bf_user");
    setAuth(null);
  };

  // Profile
  const [profile, setProfile] = useState(() => {
    try {
      const stored = localStorage.getItem("bf_profile");
      return stored ? JSON.parse(stored) : DEFAULT_PROFILE;
    } catch (e) { return DEFAULT_PROFILE; }
  });

  // Build state
  const [overrides, setOverrides] = useState({});
  const [touched,   setTouched]   = useState(() => new Set(["frame"]));
  const [drawerSlot, setDrawerSlot] = useState(null);
  const [garageOpen,  setGarageOpen]  = useState(false);
  const [compareOpen, setCompareOpen] = useState(false);

  // Saved builds — synced with backend when authenticated
  const [saved, setSaved] = useState([]);

  // Tweaks
  const [tweaks, setTweak] = useTweaks ? useTweaks(TWEAK_DEFAULTS) : [TWEAK_DEFAULTS, () => {}];

  // Persist profile locally
  useEffect(() => {
    localStorage.setItem("bf_profile", JSON.stringify(profile));
  }, [profile]);

  // Apply accent CSS variable
  useEffect(() => {
    const accent = tweaks.accent || "#da291c";
    document.documentElement.style.setProperty("--accent", accent);
    const isLight = ["#f6e500", "#fff200", "#ffffff"].includes(accent.toLowerCase());
    document.documentElement.style.setProperty("--accent-ink", isLight ? "#181818" : "#ffffff");
    const r = parseInt(accent.slice(1,3), 16);
    const g = parseInt(accent.slice(3,5), 16);
    const b = parseInt(accent.slice(5,7), 16);
    document.documentElement.style.setProperty("--accent-soft", `rgba(${r},${g},${b},0.15)`);
  }, [tweaks.accent]);

  // Load plan + saved builds when auth changes
  useEffect(() => {
    if (!auth) { setSaved([]); setPlan("free"); return; }
    fetch("/api/auth/me", { headers: { Authorization: `Bearer ${auth.token}` } })
      .then(r => r.ok ? r.json() : {})
      .then(data => setPlan(data.plan || "free"))
      .catch(() => {});
    fetch("/api/builds", { headers: { Authorization: `Bearer ${auth.token}` } })
      .then(r => r.ok ? r.json() : [])
      .then(data => setSaved(Array.isArray(data) ? data : []))
      .catch(() => setSaved([]));
  }, [auth]);

  // Generate build from profile
  const baseResult = useMemo(() => {
    return window.BikeEngine.generateBuild(profile, frames, components);
  }, [profile, frames, components]);

  // Apply manual overrides on top of the auto build
  const result = useMemo(() => {
    if (Object.keys(overrides).length === 0) return baseResult;
    const newBuild = { ...baseResult.build };
    for (const slot in overrides) {
      const id   = overrides[slot];
      const pool = slot === "frame" ? frames : components[SLOT_TO_POOL[slot]];
      const found = pool && pool.find(p => p.id === id);
      if (found) newBuild[slot] = found;
    }
    let total = 0;
    Object.values(newBuild).forEach(v => { if (v && v.price) total += v.price; });
    const scores = window.BikeEngine.calculateScores(newBuild, profile);
    return { ...baseResult, build: newBuild, total_price: total, scores };
  }, [baseResult, overrides, frames, components, profile]);

  const handleSwap = (slot) => {
    setTouched(prev => { const n = new Set(prev); n.add(slot); return n; });
    setDrawerSlot(slot);
  };

  const handlePick = (item) => {
    setOverrides({ ...overrides, [drawerSlot]: item.id });
    setTouched(prev => { const n = new Set(prev); n.add(drawerSlot); return n; });
    setDrawerSlot(null);
  };

  const handleReset = () => {
    setProfile(DEFAULT_PROFILE);
    setOverrides({});
    setTouched(new Set(["frame"]));
  };

  const handleSave = async () => {
    if (!auth) return;
    const id        = "build_" + Date.now();
    const title     = result.build.frame.name;
    const photoKey  = `image-slot:bike-photo-${result.build.frame.id}`;
    let   thumbnail = null;
    try { thumbnail = localStorage.getItem(photoKey); } catch {}

    const entry = {
      id,
      title,
      profile,
      build:   Object.fromEntries(Object.entries(result.build).map(([k, v]) => [k, v ? v.id : null])),
      scores:  result.scores,
      total:   result.total_price,
      thumbnail,
      created: Date.now()
    };

    try {
      const res = await fetch("/api/builds", {
        method:  "POST",
        headers: authHeaders(auth.token),
        body:    JSON.stringify(entry)
      });
      if (res.status === 403) {
        const data = await res.json();
        if (data.error === "limit_reached") { setUpgradeOpen(true); return; }
      }
      if (res.ok) {
        setSaved(prev => [{ ...entry }, ...prev]);
        setGarageOpen(true);
      }
    } catch {}
  };

  const handleLoadSaved = (entry) => {
    setProfile(entry.profile);
    const ovr = {};
    for (const slot in entry.build) {
      if (entry.build[slot]) ovr[slot] = entry.build[slot];
    }
    setOverrides(ovr);
    setGarageOpen(false);
  };

  const handleDeleteSaved = async (id) => {
    setSaved(prev => prev.filter(s => s.id !== id));
    if (!auth) return;
    try {
      await fetch(`/api/builds/${id}`, {
        method:  "DELETE",
        headers: { Authorization: `Bearer ${auth.token}` }
      });
    } catch {}
  };

  // ── Auth gate ──────────────────────────────────────────────────────────────
  if (!auth) {
    return <AuthScreen onAuth={handleAuth} />;
  }

  // ── Layout ─────────────────────────────────────────────────────────────────
  const layout = tweaks.layout || "studio";
  const Layout = layout === "editorial" ? EditorialLayout
               : layout === "garage"    ? GarageLayout
               : StudioLayout;

  const layoutProps = {
    profile,
    onProfileChange: (p) => { setProfile(p); setOverrides({}); },
    result,
    frame:      result.build.frame,
    touched,
    onSwap:     handleSwap,
    onSave:     handleSave,
    onReset:    handleReset,
    onOpenGarage: () => setGarageOpen(true),
    onUpgrade:  () => setUpgradeOpen(true),
    savedCount: saved.length,
    plan,
    user:       auth.user,
    onLogout:   handleLogout
  };

  let drawerPool = null;
  if (drawerSlot) {
    drawerPool = drawerSlot === "frame"
      ? frames
      : (components[SLOT_TO_POOL[drawerSlot]] || []);
  }

  return (
    <>
      <Layout {...layoutProps} />

      {drawerSlot && (
        <ComponentDrawer
          slot={drawerSlot}
          currentItem={result.build[drawerSlot]}
          pool={drawerPool}
          frame={result.build.frame}
          profile={profile}
          onPick={handlePick}
          onClose={() => setDrawerSlot(null)}
        />
      )}

      {garageOpen && (
        <GarageDrawer
          saved={saved}
          onClose={() => setGarageOpen(false)}
          onLoad={handleLoadSaved}
          onDelete={handleDeleteSaved}
          onCompare={() => { setGarageOpen(false); setCompareOpen(true); }}
          user={auth.user}
          onLogout={handleLogout}
          plan={plan}
          onUpgrade={() => { setGarageOpen(false); setUpgradeOpen(true); }}
        />
      )}

      {compareOpen && (
        <CompareView
          saved={saved}
          frames={frames}
          components={components}
          onClose={() => setCompareOpen(false)}
        />
      )}

      {upgradeOpen && (
        <UpgradeModal
          plan={plan}
          token={auth.token}
          onClose={() => setUpgradeOpen(false)}
        />
      )}

      {TweaksPanel && (
        <TweaksPanel title="Tweaks">
          <TweakSection label="Layout" />
          <TweakRadio label="Variante" value={tweaks.layout}
            options={[
              { value: "studio",    label: "Studio"    },
              { value: "editorial", label: "Editorial" },
              { value: "garage",    label: "Garage"    }
            ]}
            onChange={(v) => setTweak("layout", v)} />
          <TweakSection label="Akzent-Farbe" />
          <TweakColor label="Akzent" value={tweaks.accent}
            options={ACCENT_PALETTE.map(p => p.hex)}
            onChange={(v) => setTweak("accent", v)} />
          <TweakSection label="Aktionen" />
          <TweakButton label="Profil zurücksetzen"    onClick={handleReset} />
          <TweakButton label="Overrides verwerfen"    onClick={() => setOverrides({})} secondary />
          <TweakButton label="Abmelden"               onClick={handleLogout} secondary />
        </TweaksPanel>
      )}
    </>
  );
}

// ── Boot ───────────────────────────────────────────────────────────────────────
async function boot() {
  const [framesRes, componentsRes] = await Promise.all([
    fetch("/data/frames.json"),
    fetch("/data/components.json")
  ]);
  const frames     = await framesRes.json();
  const components = await componentsRes.json();
  ReactDOM.createRoot(document.getElementById("root")).render(
    <App frames={frames} components={components} />
  );
}

boot();
