import { Injectable, inject, signal } from '@angular/core';
import { RemoteData } from '@shared/application/remote-data';
import { Aanvraag } from '@registratie/domain/aanvraag';
import {
  ApplicationsAdapter,
  parseApplications,
} from '@registratie/infrastructure/applications.adapter';

type Err = Error | undefined;

/**
 * The dashboard's view of the user's applications (aanvragen) — the backend is the
 * system of record (PRD 0001). One root singleton OWNS the list as a writable
 * RemoteData signal (CLAUDE.md §3: change state only through methods). Cancel removes
 * the row SYNCHRONOUSLY, so the block disappears deterministically — no dependence on
 * change-detection timing, HTTP caching, or a resource `reload()`. `reload()` re-fetches
 * so a page revisit reflects auto-approval (Concept → In behandeling → Goedgekeurd is
 * computed server-side on read).
 */
@Injectable({ providedIn: 'root' })
export class ApplicationsStore {
  private adapter = inject(ApplicationsAdapter);

  private state = signal<RemoteData<Err, Aanvraag[]>>({ tag: 'Loading' });
  readonly applications = this.state.asReadonly();

  constructor() {
    void this.load();
  }

  /** Fetch + parse at the trust boundary, then publish as RemoteData. Keeps the
      last-good value on a resync (only shows Loading on the first load). */
  async load() {
    if (this.state().tag !== 'Success') this.state.set({ tag: 'Loading' });
    try {
      const parsed = parseApplications(await this.adapter.list());
      this.state.set(
        parsed.ok
          ? { tag: 'Success', value: parsed.value }
          : { tag: 'Failure', error: new Error(parsed.error) },
      );
    } catch (e) {
      this.state.set({ tag: 'Failure', error: e as Error });
    }
  }

  /** Re-fetch (e.g. on dashboard revisit) so auto-approval transitions show up. */
  reload() {
    void this.load();
  }

  /** Cancel a Concept: drop it now (synchronous, guaranteed), then confirm the DELETE.
      No resync — the delete succeeded, so the optimistic removal is authoritative. */
  async cancel(id: string) {
    const before = this.state();
    if (before.tag === 'Success') {
      this.state.set({ tag: 'Success', value: before.value.filter((a) => a.id !== id) });
    }
    try {
      await this.adapter.cancel(id);
    } catch {
      this.state.set(before); // roll back: the block reappears
    }
  }
}
