import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
import { useClient } from 'hooks/useClient';

// Reading and driving the app store. One query, four verbs.

export type InstallMode = 'existing' | 'provisioned' | 'config';

export type ConfigField = {
  key: string;
  label: string;
  type: 'url' | 'text' | 'secret';
  required: boolean;
  placeholder?: string;
  help?: string;
};

export type StoreItem = {
  id: string;
  label: string;
  summary: string;
  modes: InstallMode[];
  members: 'accounts' | 'invite' | 'none';
  memberOutcome: string;
  existingFields?: ConfigField[];
  configFields?: ConfigField[];
  install: {
    status: 'not-installed' | 'pending' | 'installing' | 'installed' | 'failed' | 'blocked';
    enabled: boolean;
    mode: string | null;
    lastError: string | null;
    completedSteps: string[];
  };
  processStatus: string | null;
};

export type InstallOutcome =
  | { status: 'installed'; completed: string[] }
  | { status: 'blocked'; completed: string[]; at: string; reason: string; completeAt?: string }
  | { status: 'failed'; completed: string[]; at: string; error: string };

const STORE_KEY = ['app-store'];

export function useAppStore() {
  const client = useClient();
  const queryClient = useQueryClient();

  const { data, isLoading, error } = useQuery({
    queryKey: STORE_KEY,
    queryFn: () => client.get<{ items: StoreItem[] }>('/app-store'),
  });

  // Every verb invalidates the same key, and also the capability answer: installing changes which dock
  // tiles exist, and a store that updated while the dock kept the old list would be visibly wrong on
  // the same screen.
  const invalidate = () => {
    void queryClient.invalidateQueries({ queryKey: STORE_KEY });
    void queryClient.invalidateQueries({ queryKey: ['self-capabilities'] });
  };

  const install = useMutation({
    mutationFn: (vars: { id: string; mode: InstallMode; values: Record<string, string> }) =>
      client.post<{ outcome: InstallOutcome; log: string[] }>(`/app-store/${vars.id}/install`, {
        mode: vars.mode,
        values: vars.values,
      }),
    onSuccess: invalidate,
  });

  const setEnabled = useMutation({
    mutationFn: (vars: { id: string; enabled: boolean }) =>
      client.post(`/app-store/${vars.id}/${vars.enabled ? 'enable' : 'disable'}`, {}),
    onSuccess: invalidate,
  });

  const uninstall = useMutation({
    mutationFn: (id: string) => client.post(`/app-store/${id}/uninstall`, {}),
    onSuccess: invalidate,
  });

  return { items: data?.items ?? [], isLoading, error, install, setEnabled, uninstall };
}
