import { effect, inject, Injectable, Injector, signal, TemplateRef } from '@angular/core';
import { BehaviorSubject } from 'rxjs';
import { getErrorMessage, } from '../utils/util';

export type PromptType = 'Yes-No' | 'Save-DontSave-Cancel' | 'Apply-Discard-Cancel' | 'Custom';

export interface PromptSettings {
  title: string;
  content: string | TemplateRef<unknown>;
  type: PromptType;
  typeModifier?: string;
  customButtons?: TemplateRef<unknown>;
}

export enum promptAction {
  Yes,
  No,
  Save,
  DontSave,
  Apply,
  Discard,
  Cancel,
  Refresh,
  Regenerate,
  SnapshotLines
}

@Injectable({ providedIn: 'root' })
export class MessageService {
  errorMessage$ = new BehaviorSubject<string>(null)
  infoMessage$ = new BehaviorSubject<string>(null)
  promptTitle = signal<string>(null);
  promptMessage = signal<string | TemplateRef<unknown>>(null);
  promptResult = signal<promptAction>(null);
  promptType = signal<PromptType>(null);
  promptTypeModifier = signal<string>(null);
  promptCustomButtons = signal<TemplateRef<unknown>>(null);
  private injector = inject(Injector);

  throw(error: unknown) {
    console.error(error);
    const errorMessage = getErrorMessage(error as unknown);
    this.errorMessage$.next(errorMessage);
  }

  info(message: string) {
    this.infoMessage$.next(message)
  }

  prompt(message: string, title?: string, type?: PromptType, typeModifier?: string): Promise<promptAction>;
  prompt(ps: PromptSettings): Promise<promptAction>;
  prompt(messageOrSettings: string | PromptSettings, title?: string, type?: PromptType) {
    let ps: PromptSettings

    if (typeof messageOrSettings === 'object')
      ps = messageOrSettings as PromptSettings
    else
      ps = { content: messageOrSettings, title, type } as PromptSettings;

    this.promptTitle.set(ps.title ?? 'Please confirm');
    this.promptMessage.set(ps.content ?? 'Are you sure?');
    this.promptType.set(ps.type ?? 'Yes-No');
    this.promptTypeModifier.set(ps.typeModifier ?? '');
    this.promptCustomButtons.set(ps.customButtons ?? null);

    return new Promise<promptAction>((resolve) => {
      const signalWatcher = effect(() => {
        const result = this.promptResult();

        if (result !== null) {
          resolve(result);
          this.promptMessage.set(null);
          this.promptResult.set(null);
          signalWatcher.destroy();
        }
      }, { injector: this.injector });
    });
  }
}
