import { Injectable, inject, resource } from '@angular/core';
import { Result, ok, err } from '@shared/kernel/fp';
import { DuoLookupDto, DuoDiplomaDto, PolicyQuestionDto, ManualDiplomaPolicyDto } from '@registratie/contracts/duo-diplomas.dto';
import { ApiClient } from '@shared/infrastructure/api-client';

/**
 * Infrastructure adapter for the DUO diploma lookup, reached only through our own
 * ("BFF-lite") endpoint — the anti-corruption boundary. The response carries the
 * user's diplomas (each with its server-computed beroep + policy questions) and
 * the manual-entry fallback policy. The frontend renders; it does not derive.
 * Data comes from the .NET backend (`GET /api/duo/diplomas`) via the typed client.
 */
@Injectable({ providedIn: 'root' })
export class DuoAdapter {
  private client = inject(ApiClient);

  diplomasResource() {
    return resource({ loader: () => this.client.diplomas() });
  }
}

function parseQuestions(json: unknown): PolicyQuestionDto[] | null {
  if (!Array.isArray(json)) return null;
  const out: PolicyQuestionDto[] = [];
  for (const q of json) {
    if (typeof q !== 'object' || q === null) return null;
    const p = q as Partial<PolicyQuestionDto>;
    if (typeof p.id !== 'string' || typeof p.vraag !== 'string' || (p.type !== 'ja-nee' && p.type !== 'tekst')) return null;
    out.push({ id: p.id, vraag: p.vraag, type: p.type });
  }
  return out;
}

/** Trust-boundary parse: validate the untrusted response shape (diplomas, each
    with derived beroep + policy questions, plus the manual-entry fallback). */
export function parseDuoLookup(json: unknown): Result<string, DuoLookupDto> {
  if (typeof json !== 'object' || json === null) return err('duo-lookup: not an object');
  const dto = json as Partial<DuoLookupDto>;
  if (!Array.isArray(dto.diplomas)) return err('duo-lookup: missing diplomas');

  const diplomas: DuoDiplomaDto[] = [];
  for (const item of dto.diplomas) {
    if (typeof item !== 'object' || item === null) return err('duo-lookup: invalid diploma');
    const d = item as Partial<DuoDiplomaDto>;
    const vragen = parseQuestions(d.policyQuestions);
    if (typeof d.id !== 'string' || typeof d.naam !== 'string' || typeof d.beroep !== 'string' || vragen === null) {
      return err('duo-lookup: missing/invalid diploma fields');
    }
    diplomas.push({ id: d.id, naam: d.naam, instelling: d.instelling ?? '', jaar: typeof d.jaar === 'number' ? d.jaar : 0, beroep: d.beroep, policyQuestions: vragen });
  }

  const hm = dto.handmatig;
  const hmVragen = hm ? parseQuestions(hm.policyQuestions) : null;
  if (!hm || !Array.isArray(hm.beroepen) || hmVragen === null) {
    return err('duo-lookup: missing/invalid handmatig fallback');
  }
  const handmatig: ManualDiplomaPolicyDto = { beroepen: hm.beroepen, policyQuestions: hmVragen };

  return ok({ diplomas, handmatig });
}
