import React, { createContext, useCallback, useContext, useEffect, useMemo, useState } from 'react';
import { RestClient, type RouteBinding, type RouteDecision } from '@insignia/iios-kernel-client';

const CommunityContext = createContext<RestClient | null>(null);

export function CommunityProvider({
  serviceUrl,
  token,
  children,
}: {
  serviceUrl: string;
  token: string;
  children: React.ReactNode;
}): React.ReactElement {
  const client = useMemo(() => new RestClient({ serviceUrl, token }), [serviceUrl, token]);
  return <CommunityContext.Provider value={client}>{children}</CommunityContext.Provider>;
}

function useClient(): RestClient {
  const c = useContext(CommunityContext);
  if (!c) throw new Error('community hooks must be used within <CommunityProvider>');
  return c;
}

/** Manage route bindings (origin→destination rules). */
export function useBindings(): {
  bindings: RouteBinding[];
  refresh: () => Promise<void>;
  createBinding: (input: Partial<RouteBinding>) => Promise<RouteBinding>;
} {
  const client = useClient();
  const [bindings, setBindings] = useState<RouteBinding[]>([]);
  const refresh = useCallback(async () => {
    try {
      setBindings(await client.listBindings());
    } catch {
      /* transient */
    }
  }, [client]);
  useEffect(() => {
    void refresh();
  }, [refresh]);
  const createBinding = async (input: Partial<RouteBinding>) => {
    const b = await client.createBinding(input);
    await refresh();
    return b;
  };
  return { bindings, refresh, createBinding };
}

/** Preview-first: simulate an interaction against the bindings (no send). */
export function useRoutePreview(): (interactionId: string, originChannelType: string, originRef?: string) => Promise<RouteDecision[]> {
  const client = useClient();
  return async (interactionId, originChannelType, originRef) =>
    (await client.simulateRoute({ interactionId, originChannelType, originRef })).decisions;
}

/** Pending decisions + admin approve/deny. */
export function useRouteDecisions(opts?: { state?: string; pollMs?: number }): {
  decisions: RouteDecision[];
  refresh: () => Promise<void>;
  approve: (id: string) => Promise<void>;
  deny: (id: string) => Promise<void>;
} {
  const client = useClient();
  const [decisions, setDecisions] = useState<RouteDecision[]>([]);
  const refresh = useCallback(async () => {
    try {
      setDecisions(await client.listRouteDecisions(opts?.state));
    } catch {
      /* transient */
    }
  }, [client, opts?.state]);
  useEffect(() => {
    void refresh();
    const t = setInterval(() => void refresh(), opts?.pollMs ?? 3000);
    return () => clearInterval(t);
  }, [refresh, opts?.pollMs]);
  const approve = async (id: string) => {
    await client.approveDecision(id);
    await refresh();
  };
  const deny = async (id: string) => {
    await client.denyDecision(id);
    await refresh();
  };
  return { decisions, refresh, approve, deny };
}
