import { Injectable, computed, inject } from '@angular/core';
import { RemoteData, fromResource } from '@shared/application/remote-data';
import { DuoLookupDto } from '../contracts/duo-diplomas.dto';
import { BrpAdapter, parseBrpAddress } from '../infrastructure/brp.adapter';
import { DuoAdapter, parseDuoLookup } from '../infrastructure/duo.adapter';

type Err = Error | undefined;

/**
 * Application-layer facade for the registratie wizard's two lookups (BRP address,
 * DUO diplomas). It owns the httpResources (created here, in the required injection
 * context), runs the trust-boundary parse, and exposes RemoteData / derived signals
 * — so the UI reaches the network through application/, never infrastructure/
 * directly (CLAUDE.md §1: ui → application → domain). Same facade shape as
 * BigProfileStore.
 */
@Injectable({ providedIn: 'root' })
export class RegistratieLookupStore {
  private brp = inject(BrpAdapter);
  private duo = inject(DuoAdapter);

  private adresRes = this.brp.adresResource();
  private diplomasRes = this.duo.diplomasResource();

  /** BRP lookup outcome. A failure or "geen adres" never blocks the wizard — both
      fall back to manual entry (PRD §7). 'geen' covers both no-address-found and a
      malformed response; 'fout' is an unreachable BRP. */
  readonly adresStatus = computed<'laden' | 'gevonden' | 'geen' | 'fout'>(() => {
    const st = this.adresRes.status();
    if (st === 'loading' || st === 'reloading') return 'laden';
    if (st === 'error') return 'fout';
    const json = this.adresRes.value();
    const parsed = json !== undefined ? parseBrpAddress(json) : null;
    return parsed && parsed.ok && parsed.value.gevonden ? 'gevonden' : 'geen';
  });

  /** The address to prefill the draft with, once BRP resolves with a found address;
      null otherwise (loading, error, no address, malformed). */
  readonly prefillAdres = computed<{ straat: string; postcode: string; woonplaats: string } | null>(
    () => {
      const json = this.adresRes.value();
      if (json === undefined) return null;
      const parsed = parseBrpAddress(json);
      return parsed.ok && parsed.value.gevonden && parsed.value.adres ? parsed.value.adres : null;
    },
  );

  /** The DUO lookup (diplomas + manual fallback), validated at the trust boundary. */
  readonly duoLookup = computed<RemoteData<Err, DuoLookupDto>>(() => {
    const rd = fromResource(this.diplomasRes);
    if (rd.tag !== 'Success') return rd;
    const parsed = parseDuoLookup(rd.value);
    return parsed.ok
      ? { tag: 'Success', value: parsed.value }
      : { tag: 'Failure', error: new Error(parsed.error) };
  });

  /** Reload the BRP lookup (e.g. when the wizard restarts) so the address re-prefills. */
  reloadAdres() {
    this.adresRes.reload();
  }
}
