import { hasComponentsEvenIfNoNext } from '@defra/forms-model';
import Boom from '@hapi/boom';
import { ComponentCollection } from "../components/ComponentCollection.js";
import { FileUploadField } from "../components/FileUploadField.js";
import { getAnswer } from "../components/helpers/components.js";
import { checkEmailAddressForLiveFormSubmission, checkFormStatus, getCacheService } from "../helpers.js";
import { SummaryViewModel } from "../models/index.js";
import { QuestionPageController } from "./QuestionPageController.js";
import { FormAction } from "../../../routes/types.js";
export class SummaryPageController extends QuestionPageController {
  allowSaveAndExit = true;

  /**
   * The controller which is used when Page["controller"] is defined as "./pages/summary.js"
   */

  constructor(model, pageDef) {
    super(model, pageDef);
    this.viewName = 'summary';

    // Components collection
    this.collection = new ComponentCollection(hasComponentsEvenIfNoNext(pageDef) ? pageDef.components : [], {
      model,
      page: this
    });
  }
  getSummaryViewModel(request, context) {
    const viewModel = new SummaryViewModel(request, this, context);
    const {
      query
    } = request;
    const {
      payload,
      errors
    } = context;
    const components = this.collection.getViewModel(payload, errors, query);

    // We already figure these out in the base page controller. Take them and apply them to our page-specific model.
    // This is a stop-gap until we can add proper inheritance in place.
    viewModel.backLink = this.getBackLink(request, context);
    viewModel.feedbackLink = this.feedbackLink;
    viewModel.phaseTag = this.phaseTag;
    viewModel.components = components;
    viewModel.allowSaveAndExit = this.shouldShowSaveAndExit(request.server);
    viewModel.errors = errors;
    return viewModel;
  }

  /**
   * Returns an async function. This is called in plugin.ts when there is a GET request at `/{id}/{path*}`,
   */
  makeGetRouteHandler() {
    return async (request, context, h) => {
      const {
        viewName
      } = this;
      const viewModel = this.getSummaryViewModel(request, context);
      viewModel.hasMissingNotificationEmail = await this.hasMissingNotificationEmail(request, context);
      return h.view(viewName, viewModel);
    };
  }

  /**
   * Returns an async function. This is called in plugin.ts when there is a POST request at `/{id}/{path*}`.
   * If a form is incomplete, a user will be redirected to the start page.
   */
  makePostRouteHandler() {
    return async (request, context, h) => {
      // Check if this is a save-and-exit action
      const {
        action
      } = request.payload;
      if (action === FormAction.SaveAndExit) {
        return this.handleSaveAndExit(request, context, h);
      }
      return this.handleFormSubmit(request, context, h);
    };
  }
  async handleFormSubmit(request, context, h) {
    const {
      model
    } = this;
    const {
      params
    } = request;
    const cacheService = getCacheService(request.server);
    const {
      formsService
    } = this.model.services;
    const {
      getFormMetadata
    } = formsService;

    // Get the form metadata using the `slug` param
    const formMetadata = await getFormMetadata(params.slug);
    const {
      notificationEmail
    } = formMetadata;
    const {
      isPreview
    } = checkFormStatus(request.params);
    const emailAddress = notificationEmail ?? this.model.def.outputEmail;
    checkEmailAddressForLiveFormSubmission(emailAddress, isPreview);

    // Send submission email
    if (emailAddress) {
      const viewModel = this.getSummaryViewModel(request, context);
      await submitForm(context, request, viewModel, model, emailAddress, formMetadata);
    }
    await cacheService.setConfirmationState(request, {
      confirmed: true
    });

    // Clear all form data
    await cacheService.clearState(request);
    return this.proceed(request, h, this.getStatusPath());
  }
  get postRouteOptions() {
    return {
      ext: {
        onPreHandler: {
          method(request, h) {
            return h.continue;
          }
        }
      }
    };
  }
}
export async function submitForm(context, request, summaryViewModel, model, emailAddress, formMetadata) {
  await extendFileRetention(model, context.state, emailAddress);
  const formStatus = checkFormStatus(request.params);
  const logTags = ['submit', 'submissionApi'];
  request.logger.info(logTags, 'Preparing email', formStatus);

  // Get detail items
  const items = getFormSubmissionData(summaryViewModel.context, summaryViewModel.details);

  // Submit data
  request.logger.info(logTags, 'Submitting data');
  const submitResponse = await submitData(model, items, emailAddress, request.yar.id);
  if (submitResponse === undefined) {
    throw Boom.badRequest('Unexpected empty response from submit api');
  }
  return model.services.outputService.submit(context, request, model, emailAddress, items, submitResponse, formMetadata);
}
async function extendFileRetention(model, state, updatedRetrievalKey) {
  const {
    formSubmissionService
  } = model.services;
  const {
    persistFiles
  } = formSubmissionService;
  const files = [];

  // For each file upload component with files in
  // state, add the files to the batch getting persisted
  model.pages.forEach(page => {
    const fileUploadComponents = page.collection.fields.filter(component => component instanceof FileUploadField);
    fileUploadComponents.forEach(component => {
      const values = component.getFormValueFromState(state);
      if (!values?.length) {
        return;
      }
      files.push(...values.map(({
        status
      }) => ({
        fileId: status.form.file.fileId,
        initiatedRetrievalKey: status.metadata.retrievalKey
      })));
    });
  });
  if (files.length) {
    return persistFiles(files, updatedRetrievalKey);
  }
}
function submitData(model, items, retrievalKey, sessionId) {
  const {
    formSubmissionService
  } = model.services;
  const {
    submit
  } = formSubmissionService;
  const payload = {
    sessionId,
    retrievalKey,
    // Main form answers
    main: items.filter(item => 'field' in item).map(item => ({
      name: item.name,
      title: item.label,
      value: getAnswer(item.field, item.state, {
        format: 'data'
      })
    })),
    // Repeater form answers
    repeaters: items.filter(item => 'subItems' in item).map(item => ({
      name: item.name,
      title: item.label,
      // Repeater item values
      value: item.subItems.map(detailItems => detailItems.map(subItem => ({
        name: subItem.name,
        title: subItem.label,
        value: getAnswer(subItem.field, subItem.state, {
          format: 'data'
        })
      })))
    }))
  };
  return submit(payload);
}
export function getFormSubmissionData(context, details) {
  return context.relevantPages.map(({
    href
  }) => details.flatMap(({
    items
  }) => items.filter(({
    page
  }) => page.href === href))).flat();
}
//# sourceMappingURL=SummaryPageController.js.map