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

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

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

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

export function useMeetings(opts?: { pollMs?: number }): { meetings: Meeting[]; refresh: () => Promise<void> } {
  const client = useClient();
  const [meetings, setMeetings] = useState<Meeting[]>([]);
  const refresh = useCallback(async () => {
    try {
      setMeetings(await client.listMeetings());
    } catch {
      /* transient */
    }
  }, [client]);
  useEffect(() => {
    void refresh();
    if (!opts?.pollMs) return;
    const t = setInterval(() => void refresh(), opts.pollMs);
    return () => clearInterval(t);
  }, [refresh, opts?.pollMs]);
  return { meetings, refresh };
}

export function useMeeting(id: string | null): { meeting: Meeting | null; refresh: () => Promise<void> } {
  const client = useClient();
  const [meeting, setMeeting] = useState<Meeting | null>(null);
  const refresh = useCallback(async () => {
    if (!id) return setMeeting(null);
    try {
      setMeeting(await client.getMeeting(id));
    } catch {
      /* transient */
    }
  }, [client, id]);
  useEffect(() => {
    void refresh();
  }, [refresh]);
  return { meeting, refresh };
}

export function useSchedule(): (input: Parameters<RestClient['scheduleMeeting']>[0]) => Promise<Meeting> {
  const client = useClient();
  return (input) => client.scheduleMeeting(input);
}

export function useConsent(): {
  setConsent: (meetingId: string, actorRefId: string, status: string) => Promise<unknown>;
  generateTranscript: (meetingId: string) => Promise<unknown>;
} {
  const client = useClient();
  return {
    setConsent: (meetingId, actorRefId, status) => client.setConsent(meetingId, actorRefId, status),
    generateTranscript: (meetingId) => client.generateTranscript(meetingId),
  };
}

export function useSummarize(): (meetingId: string) => Promise<Meeting> {
  const client = useClient();
  return (meetingId) => client.summarizeMeeting(meetingId);
}

export function useActionItems(meetingId: string | null): { actionItems: MeetingActionItem[]; refresh: () => Promise<void> } {
  const client = useClient();
  const [actionItems, setActionItems] = useState<MeetingActionItem[]>([]);
  const refresh = useCallback(async () => {
    if (!meetingId) return setActionItems([]);
    try {
      setActionItems(await client.listActionItems(meetingId));
    } catch {
      /* transient */
    }
  }, [client, meetingId]);
  useEffect(() => {
    void refresh();
  }, [refresh]);
  return { actionItems, refresh };
}
