import { Button, Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, Input, Label } from '@learnitive/ui-components';
import React from 'react';

type ConfirmRequest = {
  kind: 'confirm';
  title: string;
  description: string;
  confirmText: string;
  cancelText: string;
  tone: 'default' | 'destructive';
  resolve: (value: boolean) => void;
};

type PromptRequest = {
  kind: 'prompt';
  title: string;
  description: string;
  label: string;
  initialValue: string;
  placeholder: string;
  confirmText: string;
  cancelText: string;
  resolve: (value: string | null) => void;
};

type PageModalRequest = ConfirmRequest | PromptRequest;

type ConfirmOptions = {
  title: string;
  description: string;
  confirmText?: string;
  cancelText?: string;
  tone?: 'default' | 'destructive';
};

type PromptOptions = {
  title: string;
  description?: string;
  label?: string;
  initialValue?: string;
  placeholder?: string;
  confirmText?: string;
  cancelText?: string;
};

const queue: PageModalRequest[] = [];
const listeners = new Set<() => void>();

function emit() {
  for (const listener of listeners) listener();
}

function enqueue(request: PageModalRequest) {
  queue.push(request);
  emit();
}

export function requestPageConfirm(options: ConfirmOptions): Promise<boolean> {
  return new Promise((resolve) => {
    enqueue({
      kind: 'confirm',
      title: options.title,
      description: options.description,
      confirmText: options.confirmText ?? 'Continue',
      cancelText: options.cancelText ?? 'Cancel',
      tone: options.tone ?? 'default',
      resolve,
    });
  });
}

export function requestPagePrompt(options: PromptOptions): Promise<string | null> {
  return new Promise((resolve) => {
    enqueue({
      kind: 'prompt',
      title: options.title,
      description: options.description ?? '',
      label: options.label ?? options.title,
      initialValue: options.initialValue ?? '',
      placeholder: options.placeholder ?? '',
      confirmText: options.confirmText ?? 'Continue',
      cancelText: options.cancelText ?? 'Cancel',
      resolve,
    });
  });
}

export function PageModalHost() {
  const [, rerender] = React.useReducer((value) => value + 1, 0);
  React.useEffect(() => {
    const listener = () => rerender();
    listeners.add(listener);
    return function unsubscribePageModalHost(): void {
      void listeners.delete(listener);
    };
  }, []);

  const active = queue[0];
  const [inputValue, setInputValue] = React.useState('');
  React.useEffect(() => {
    if (active?.kind === 'prompt') setInputValue(active.initialValue);
  }, [active]);

  const finish = React.useCallback((value: boolean | string | null) => {
    const current = queue.shift();
    if (!current) return;
    if (current.kind === 'confirm') current.resolve(Boolean(value));
    else current.resolve(typeof value === 'string' ? value : null);
    emit();
  }, []);

  if (!active) return null;

  return (
    <Dialog open onOpenChange={(open) => { if (!open) finish(active.kind === 'confirm' ? false : null); }}>
      <DialogContent className="sm:max-w-md" aria-describedby="interactive-page-modal-description">
        <DialogHeader>
          <DialogTitle>{active.title}</DialogTitle>
          {active.description ? <DialogDescription id="interactive-page-modal-description">{active.description}</DialogDescription> : null}
        </DialogHeader>
        {active.kind === 'prompt' ? (
          <form
            className="grid gap-4"
            onSubmit={(event) => {
              event.preventDefault();
              const value = inputValue.trim();
              if (!value) return;
              finish(value);
            }}
          >
            <div className="grid gap-2">
              <Label htmlFor="interactive-page-modal-input">{active.label}</Label>
              <Input
                id="interactive-page-modal-input"
                autoFocus
                value={inputValue}
                placeholder={active.placeholder}
                onChange={(event) => setInputValue(event.currentTarget.value)}
              />
            </div>
            <DialogFooter>
              <Button type="button" variant="outline" onClick={() => finish(null)}>{active.cancelText}</Button>
              <Button type="submit" disabled={!inputValue.trim()}>{active.confirmText}</Button>
            </DialogFooter>
          </form>
        ) : (
          <DialogFooter>
            <Button type="button" variant="outline" autoFocus={active.tone === 'destructive'} onClick={() => finish(false)}>{active.cancelText}</Button>
            <Button type="button" variant={active.tone === 'destructive' ? 'destructive' : 'default'} autoFocus={active.tone !== 'destructive'} onClick={() => finish(true)}>{active.confirmText}</Button>
          </DialogFooter>
        )}
      </DialogContent>
    </Dialog>
  );
}
