/**
 * @file note.ts - API wrapper for IWS5 note objects and functions.
 */

import { FetchError } from '../utils/fetchHelper.ts';
import { getAccessToken } from '../services/authService.ts';
import { StatusCodes } from 'http-status-codes';

/** Base URL for the IWS5 notes API endpoint */
export const NOTES_API_URL = window.__APP_CONFIG__?.IWS5_API_URL + '/api/Note';

/**
 * Represents a note on a work item or document as returned by the IWS5 API.
 * A note is always associated with a work item, but not always a document.
 */
export type Note = {
  /** Unique identifier of the note; absent when creating a new note */
  noteId?: number;

  /** ID of the work item this note belongs to */
  workItemId: number;

  /** ID of the document this note is linked to; null if the note is work-item-level */
  documentId: number | null;

  /** Username of the note author; populated by the server on retrieval */
  submitter?: string;

  /** ISO date string of when the note was submitted; populated by the server */
  submitDate?: string;

  /** Text content of the note; comes pre-formatted from the server */
  note: string;
};

/**
 * Retrieves notes for a given work item.
 *
 * @param workItemReferenceId ID of work item to retrieve notes for
 * @returns List of notes
 * @throws FetchError If response is not 200-class
 */
export async function listNotes(workItemReferenceId: number): Promise<Note[]> {
  const _url = NOTES_API_URL + '/' + workItemReferenceId;

  // Attempt GET /api/Note/{workItemReferenceId}
  try {
    const response = await fetch(_url.toString(), {
      method: 'GET',
      headers: {
        'Content-Type': 'application/json',
        Authorization: `Bearer ${getAccessToken()}`,
      },
    });
    if (!response.ok) {
      const errorText = await response.text();
      throw new FetchError(errorText || 'Failed to retrieve notes', response);
    }
    if (response.status === StatusCodes.NO_CONTENT) {
      return [] as Note[];
    }

    return (await response.json()).responseModel.notes as Note[];
  } catch (error) {
    throw new FetchError((error as Error).message);
  }
}

/**
 * Adds a note to a work item.
 *
 * @param note Note to be added
 * @throws FetchError If response is not 200-class
 */
export async function addNote(note: Note): Promise<Note> {
  const _url = NOTES_API_URL + '/add';

  // Attempt POST /api/Note/add
  try {
    const response = await fetch(_url.toString(), {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        Authorization: `Bearer ${getAccessToken()}`,
      },
      body: JSON.stringify(note),
    });
    if (!response.ok) {
      const errorText = await response.text();
      throw new FetchError(errorText || 'Failed to add note', response);
    }

    return (await response.json()).responseModel as Note;
  } catch (error) {
    throw new FetchError((error as Error).message);
  }
}
