// Exercise 3: multi-provider composition
//
// ConfigProvider and UserProvider are two independent providers. A leaf
// component, ProfileCard, needs to read from BOTH. Implement
// mergeProviderState (pure) used internally by a combined selector, and fix
// App so both providers actually wrap ProfileCard (currently only one does).
//
// TODO 1: implement mergeProviderState(config, user) — pure merge function
// TODO 2: fix App to nest BOTH <ConfigProvider> and <UserProvider> around <ProfileCard />

import { createContext, useContext, useState } from "react";

interface Config { locale: string; theme: "light" | "dark" }
interface UserInfo { name: string; id: string }

const ConfigContext = createContext<Config | undefined>(undefined);
const UserContext = createContext<UserInfo | undefined>(undefined);

function ConfigProvider({ children }: { children: React.ReactNode }) {
  const [config] = useState<Config>({ locale: "en-US", theme: "dark" });
  return <ConfigContext.Provider value={config}>{children}</ConfigContext.Provider>;
}

function UserProvider({ children }: { children: React.ReactNode }) {
  const [user] = useState<UserInfo>({ name: "Ana", id: "u1" });
  return <UserContext.Provider value={user}>{children}</UserContext.Provider>;
}

function useConfig(): Config {
  const ctx = useContext(ConfigContext);
  if (!ctx) throw new Error("useConfig must be used within a ConfigProvider");
  return ctx;
}

function useUser(): UserInfo {
  const ctx = useContext(UserContext);
  if (!ctx) throw new Error("useUser must be used within a UserProvider");
  return ctx;
}

// TODO 1: pure function — combine config + user into one summary object,
// e.g. { greeting: `Hello, ${user.name}`, locale: config.locale, theme: config.theme }
function mergeProviderState(config: Config, user: UserInfo) {
  return { greeting: "", locale: "", theme: "light" as const }; // TODO: fill in real values
}

function ProfileCard() {
  const config = useConfig();
  const user = useUser();
  const merged = mergeProviderState(config, user);
  return (
    <div className={merged.theme}>
      <p>{merged.greeting}</p>
      <p>locale: {merged.locale}</p>
    </div>
  );
}

// TODO 2: nest BOTH providers around ProfileCard — currently UserProvider is missing
function App() {
  return (
    <ConfigProvider>
      <ProfileCard /> {/* BUG: useUser() will throw — UserProvider is missing */}
    </ConfigProvider>
  );
}

export { App, ProfileCard, ConfigProvider, UserProvider, mergeProviderState };

// --- self-check: do not modify below this line ---
const merged = mergeProviderState({ locale: "en-US", theme: "dark" }, { name: "Ana", id: "u1" });
const ok =
  merged.greeting === "Hello, Ana" && merged.locale === "en-US" && merged.theme === "dark";
console.log(ok ? "PASS (mergeProviderState combines both sources)" : "FAIL (mergeProviderState combines both sources)");

// Verify visually: render <App /> before fixing TODO 2 — it should throw
// ("useUser must be used within a UserProvider"). After nesting
// <UserProvider> around <ProfileCard />, it should render "Hello, Ana" and
// "locale: en-US" with no error.
