{% from "govuk_frontend_jinja/components/back-link/macro.html" import govukBackLink %}
{% from "govuk_frontend_jinja/components/task-list/macro.html" import govukTaskList %}
{% from "govuk_frontend_jinja/components/summary-list/macro.html" import govukSummaryList %}
{% from "govuk_frontend_jinja/components/details/macro.html" import govukDetails %}
{% from "govuk_frontend_jinja/components/inset-text/macro.html" import govukInsetText %}
{% from "common/macros/status.html" import tasklistSectionStatusTag with context %}

{% macro collection_before(runner, override_back_link=None) %}
  {{ govukBackLink({ "text": "Back", "href": override_back_link or runner.back_url }) }}
{% endmacro %}

{% macro collection_question_with_add_another_summary_page(runner) %}
  {% if runner.add_another_summary_context %}
    {{ collection_add_another_summary(runner) }}
  {% elif runner.is_removing %}
    {{ collection_add_another_confirm_remove(runner) }}
  {% elif runner.is_clearing %}
    {{ collection_question_confirm_remove(runner) }}
  {% else %}
    {{ collection_question(runner) }}
  {% endif %}
{% endmacro %}

{% macro collection_render_single_question(form, question, interpolator, questionAsPageHeading) %}
  {% if question.data_type == enum.question_type.TEXT_MULTI_LINE %}
    {{
      form.render_question(
        question,
        params={
          "label": {"classes": "govuk-label--l" if questionAsPageHeading else "govuk-!-font-weight-bold", "isPageHeading": questionAsPageHeading},
          "maxwords": question.presentation_options.word_limit,
          "rows": question.presentation_options.rows,
          "attributes": {"data-module": "paste-html-bullets-as-markdown"},
        }
      )
    }}
  {% elif question.data_type == enum.question_type.TEXT_SINGLE_LINE or question.data_type == enum.question_type.EMAIL or question.data_type == enum.question_type.URL %}
    {{
      form.render_question(
        question,
        params={
          "label": {"classes": "govuk-label--l" if questionAsPageHeading else "govuk-!-font-weight-bold", "isPageHeading": questionAsPageHeading}
        }
      )
    }}
  {% elif question.data_type == enum.question_type.NUMBER %}
    {{
      form.render_question(
        question,
        params={
          "label": {"classes": "govuk-label--l" if questionAsPageHeading else "govuk-!-font-weight-bold" ,"isPageHeading": questionAsPageHeading},
          "inputmode": "numeric",
          "spellcheck": false,
          "classes": question.presentation_options.width or '',
          "prefix": {"text": question.presentation_options.prefix or ''},
          "suffix": {"text": question.presentation_options.suffix or ''}
        }
      )
    }}
  {% elif question.data_type == enum.question_type.YES_NO %}
    {{
      form.render_question(
        question,
        params={
          "fieldset": {"legend": {"text": interpolator(question.text), "classes": "govuk-fieldset__legend--l" if questionAsPageHeading else "govuk-!-font-weight-bold", "isPageHeading": questionAsPageHeading} },
          "classes": "govuk-radios--inline"
        }
      )
    }}
  {% elif question.data_type == enum.question_type.CHECKBOXES %}
    {{
      form.render_question(
        question,
        params={
          "fieldset": {"legend": {"text": interpolator(question.text), "classes": "govuk-fieldset__legend--l" if questionAsPageHeading else "govuk-!-font-weight-bold", "isPageHeading": questionAsPageHeading} },
        }
      )
    }}
  {% elif question.data_type == enum.question_type.DATE %}
    {{
      form.render_question(
        question,
        params={
          "fieldset": {"legend": {"text": interpolator(question.text), "classes": "govuk-fieldset__legend--l" if questionAsPageHeading else "govuk-!-font-weight-bold", "isPageHeading": questionAsPageHeading} },
          "spellcheck": false
        }
      )
    }}
  {% elif question.data_type == enum.question_type.RADIOS %}
    {% if form.get_question_field(question).widget.is_accessible_autocomplete %}
      {#
            `govuk-!-width-full` override here to line up with the default width of the accessible autocomplete component. We could potentially do something smarter, like copy the class
            from here to the enhanced autocomplete, but leaving that for a future increment.
          #}
      {{
        form.render_question(
          question,
          params={
            "label": {"classes": "govuk-fieldset__legend--l" if questionAsPageHeading else "govuk-!-font-weight-bold", "isPageHeading": questionAsPageHeading},
            "classes": "govuk-!-width-full"
          }
        )
      }}
    {% else %}
      {{
        form.render_question(
          question,
          params={
            "fieldset": {"legend": {"text": interpolator(question.text), "classes": "govuk-fieldset__legend--l" if questionAsPageHeading else "govuk-!-font-weight-bold", "isPageHeading": questionAsPageHeading} },
          }
        )
      }}
    {% endif %}
  {% elif question.data_type == enum.question_type.FILE_UPLOAD %}
    {% set existing_file_upload_answer = runner.submission.cached_get_answer_for_question(question.id, add_another_index=runner.add_another_index if runner.add_another_index is not none else none) %}

    {% if existing_file_upload_answer %}
      {% if questionAsPageHeading %}
        <h1 class="govuk-heading-l">{{ runner.interpolate(question.text) }}</h1>
      {% else %}
        <label class="govuk-label govuk-label--s govuk-!-margin-bottom-4">{{ runner.interpolate(question.text) }}</label>
      {% endif %}
      {{
        govukSummaryList({
          "rows": [{
            "key": { "text": "Your file" },
            "value": { "text": existing_file_upload_answer.filename },
            "actions": {
              "items": [{
                "href": runner.to_url(enum.form_runner_state.QUESTION, question=question, add_another_index=runner.add_another_index if runner.add_another_index is not none else none, action="clear"),
                "text": "Remove",
                "visuallyHiddenText": "your uploaded file for " ~ question.name,
                "classes": "govuk-link--no-visited-state"
              }]
            }
          }]
        })
      }}
      <p class="govuk-body">You can remove this file if you need to upload a different one.</p>
    {% else %}
      {{
        form.render_question(
          question,
          params={
            "label": {"classes": "govuk-label--l" if questionAsPageHeading else "govuk-!-font-weight-bold", "isPageHeading": questionAsPageHeading},
            "attributes": {
              "accept": (question.file_types_supported | sum(attribute='mime_types', start=[]) | join(',')) if question.file_types_supported else None
            },
            "javascript": true,
          }
        )
      }}


      {% set upload_guidance %}
        <p class="govuk-body">You can upload the following file types:</p>
        <ul class="govuk-list govuk-list--bullet">
          {% for file_type in question.file_types_supported %}
            <li>{{ file_type.value }} ({{ file_type.extensions | join(", ") }})</li>
          {% endfor %}
        </ul>
        <p class="govuk-body">Your file must be smaller than {{ question.maximum_file_size.human_readable }}.</p>
      {% endset %}
      {{
        govukDetails({
          "summaryText": "What file types can I upload?",
          "html": upload_guidance,
        })
      }}
    {% endif %}
  {% endif %}
{% endmacro %}

{% macro collection_question(runner) %}
  {% set is_group = runner.component.is_group %}
  {% set questions = runner.questions if is_group else [runner.component] %}
  {% set form = runner.question_form %}
  {% set questionAsPageHeading = not runner.component.guidance_heading and not is_group %}

  {% set contains_file_upload = questions | selectattr("data_type", "equalto", enum.question_type.FILE_UPLOAD) | list | length > 0 %}
  <form method="post" {% if contains_file_upload %}enctype="multipart/form-data"{% endif %} novalidate>
    {{ form.csrf_token }}

    <span class="govuk-caption-l">{{ runner.question_page_caption }}</span>
    {% if runner.question_page_heading %}
      <h1 class="govuk-heading-l">{{ runner.question_page_heading }}</h1>
      {{ runner.interpolate(runner.component.guidance_body) | govuk_markdown }}
    {% endif %}

    {# https://github.com/alphagov/govuk-frontend/issues/1841 #}
    {# GOV.UK Frontend macros don't let you add captions to label/legend-headings that are outside of the <h> element #}
    {# We want the caption outside of the <h> element to keep things more concise and understandable to screenreader users #}
    {# So we just manually add the caption here. #}
    {% for question in questions %}
      {{ collection_render_single_question(form, question, runner.interpolate, questionAsPageHeading) }}
    {% endfor %}
    {{ form.submit }}
  </form>
{% endmacro %}

{% macro summary_list_for_answers(container, runner, add_another_index=none, summary_title=none) %}
  {# each container context will have its own summary list which we'll populate at the end of this macro #}
  {% set form = runner.form %}
  {% set submission = runner.submission %}

  {% set add_another_contexts = [] %}
  {% set summary_list_rows = [] %}

  {% set is_add_another_group = add_another_index is not none %}
  {% set context = submission.cached_evaluation_context if not is_add_another_group else submission.cached_evaluation_context.with_add_another_context(container, submission.submission.data_manager, add_another_index=add_another_index) %}
  {% set interpolation_context = submission.cached_interpolation_context if not is_add_another_group else submission.cached_interpolation_context.with_add_another_context(container, submission.submission.data_manager, add_another_index=add_another_index, mode="interpolation") %}

  {% for question in submission.cached_get_ordered_visible_questions(container, override_context=context if is_add_another_group else none) %}
    {% if question.add_another_container and not is_add_another_group %}
      {# for the add another context we'll just include one row with a link to the full answers below #}
      {% if question.add_another_container not in (add_another_contexts | map(attribute="container")) %}
        {% set count = submission.get_count_for_add_another(question.add_another_container) %}
        {% set summaries = [] %}
        {% set status = namespace(all_answered = true) %}
        {% for i in range(count) %}
          {% set (summary, is_answered) = submission.get_answer_summary_for_add_another(question.add_another_container, add_another_index=i) %}
          {%
            do summaries.append({
              "summary_text_line": summary,
              "is_answered": is_answered
            })
          %}
          {% if not is_answered %}{% set status.all_answered = false %}{% endif %}
        {% endfor %}
        {%
          do add_another_contexts.append({
            "container": question.add_another_container,
            "count": count,
            "summaries": summaries,
            "all_answered": status.all_answered
          })
        %}

        {% set key_text = runner.interpolate(question.add_another_container.text) %}

        {# the add another context has been fully answered and should be checked on this page #}
        {% if count and status.all_answered %}
          {% set value_html %}
            <p class="govuk-body">You have added {% trans count=count %}{{ count }} answer{% pluralize %}{{ count }} answers{% endtrans %}</p>

            <p class="govuk-body">
              <a href="#{{ question.add_another_container.id }}-answers" class="govuk-link govuk-link--no-visited-state">Answers for “{{ question.add_another_container.name }}”</a>
            </p>
          {% endset %}

          {%
            set actions = [] if not runner.can_edit_question(question) else [{
              "href": runner.to_url(enum.form_runner_state.QUESTION, question=question, source=enum.form_runner_state.CHECK_YOUR_ANSWERS),
              "text": "Change",
              "visuallyHiddenText": question.add_another_container.name,
              "classes": "govuk-link--no-visited-state"
            }]
          %}
        {% else %}
          {# the add another context is partially answered and should be completed before checking here #}
          {% set value_html %}
            {% if runner.can_edit_question(question) %}
              <a href="{{ runner.to_url(enum.form_runner_state.QUESTION, question=question, source=enum.form_runner_state.CHECK_YOUR_ANSWERS) }}" class="govuk-link govuk-link--no-visited-state">
                <span>
                  {{ "Enter" if not count else "Finish entering " }}
                  {{ question.add_another_container.name | lower }}
                </span>
              </a>
            {% else %}
              <span>({{ "Not answered" if not count else "Not completely answered" }})</span>
            {% endif %}
          {% endset %}
        {% endif %}
        {%
          do summary_list_rows.append({
              "key": {"text": key_text },
              "value": {"html": value_html },
              "actions": {"items": actions } if actions else none,
          })
        %}
      {% endif %}
    {% else %}
      {# standard K:V question:answer context #}
      {% set answer = submission.cached_get_answer_for_question(question.id, add_another_index=add_another_index if add_another_index is not none else none) %}
      {% if answer is not none %}
        {% set value_html %}
          {% include answer._render_answer_template %}
        {% endset %}

        {# todo: can we "anchor" or link to the specific question if we're going to be changing a question on a same page group #}
        {%
          set actions = [] if not runner.can_edit_question(question) else [{
            "href": runner.to_url(enum.form_runner_state.QUESTION, question=question, source=enum.form_runner_state.CHECK_YOUR_ANSWERS, add_another_index=add_another_index if add_another_index is not none else none),
            "text": "Change",
            "visuallyHiddenText": question.name,
            "classes": "govuk-link--no-visited-state"
          }]
        %}
        {%
          do summary_list_rows.append({
            "key": { "text": runner.interpolate(question.text, context=interpolation_context if is_add_another_group else None) },
            "value": { "html": value_html },
            "actions": { "items": actions },
          })
        %}
      {% else %}
        {% set value_html %}
          {% if runner.can_edit_question(question) %}
            <a href="{{ runner.to_url(enum.form_runner_state.QUESTION, question=question, source=enum.form_runner_state.CHECK_YOUR_ANSWERS) }}" class="govuk-link govuk-link--no-visited-state">Enter {{ question.name }}</a>
          {% else %}
            <span>(Not answered)</span>
          {% endif %}
        {% endset %}
        {%
          do summary_list_rows.append({
            "key": { "text": runner.interpolate(question.text) },
            "value": { "html": value_html }
          })
        %}
      {% endif %}
    {% endif %}
  {% endfor %}

  {# fixme: this margin applied somewhere else #}
  {{
    govukSummaryList({
      "classes": "govuk-!-margin-bottom-9" if add_another_index is none else "",
      "rows": summary_list_rows,
      "card": {
        "title": {
          "text": summary_title if summary_title else "Answer " ~ ((add_another_index + 1) if is_add_another_group else "")
        }
      } if is_add_another_group else none
    })
  }}

  {% for context in add_another_contexts %}
    {% if context.count and context.all_answered %}
      <div class="govuk-!-margin-bottom-9">
        <h2 class="govuk-heading-m" id="{{ context.container.id }}-answers">Answers for “{{ context.container.name }}”</h2>

        {% for i in range(context.count) %}
          {{ summary_list_for_answers(context.container, runner, add_another_index=i, summary_title=context.summaries[i].summary_text_line) }}
        {% endfor %}
      </div>
    {% endif %}
  {% endfor %}
{% endmacro %}

{% macro collection_check_your_answers(runner) %}
  {% set form = runner.form %}
  {% set submission = runner.submission %}

  <span class="govuk-caption-l">{{ form.title }}</span>
  <h1 class="govuk-heading-l">{{ "Your submitted answers" if (submission.in_answers_locked_state) else "Check your answers" }}</h1>

  {% if submission.get_status_for_form(form) == enum.tasklist_section_status.CHANGES_REQUESTED or (submission.events.submission_state.is_changes_requested and not submission.events.submission_state.section_ids) %}
    <div class="govuk-inset-text">
      <strong class="govuk-tag govuk-tag--yellow govuk-!-margin-bottom-2">Changes requested</strong>
      <p class="govuk-body app-pre-markdown">{{ submission.changes_requested_reason }}</p>
    </div>
  {% endif %}

  {{ summary_list_for_answers(form, runner) }}

  {% if not runner.can_edit_form(form) %}
    <p class="govuk-body">
      <a class="govuk-link govuk-link--no-visited-state" href="{{ runner.to_url(enum.form_runner_state.TASKLIST) }}">Return to the task list</a>
    </p>
  {% else %}
    {% set check_your_answers_form = runner.check_your_answers_form %}
    <form method="post" novalidate class="govuk-!-margin-top-8">
      {{ check_your_answers_form.csrf_token }}
      {% set all_questions_answered = submission.cached_get_all_questions_are_answered_for_form(form).all_answered %}
      {% if all_questions_answered %}
        {{
          check_your_answers_form.section_completed(params={
            "fieldset": {
              "legend": {
                "text": "Have you completed this section?",
                "isPageHeading": false,
                "classes": "govuk-fieldset__legend--m"
              }
            }
          })
        }}
      {% endif %}
      {{ check_your_answers_form.submit }}
    </form>
  {% endif %}
{% endmacro %}

{% macro collection_tasklist(runner, submit_text=None, before_submission=None) %}
  {% set submission = runner.submission %}

  <div class="govuk-grid-row">
    <div class="govuk-grid-column-two-thirds">
      {% set forms = submission.get_ordered_visible_forms() %}
      {% if not forms %}
        <p class="govuk-body">This collection has no forms.</p>
      {% else %}
        {% set rows=[] %}
        {% for form in forms %}
          {% set can_start = submission.can_start_form(form) %}
          {% set hint_html = None %}

          {% if not can_start %}
            {% set link_href = None %}
            {% set blocking_sections = submission.get_referenced_forms_with_unanswered_references(form) %}
            {% set hint_html %}
              <span class="govuk-hint govuk-!-margin-bottom-0">Requires answers from {{ blocking_sections | map(attribute='title') | comma_join_items }}</span>
            {% endset %}
          {% else %}
            {% set first_question = submission.get_first_question_for_form(form) %}
            {%
              set link_href = (
                ''
                if not first_question else
                runner.to_url(enum.form_runner_state.QUESTION, question=first_question)
                if (submission.get_status_for_form(form) == enum.tasklist_section_status.NOT_STARTED and runner.can_edit_form(form)) else
                runner.to_url(enum.form_runner_state.CHECK_YOUR_ANSWERS, form=form, source=enum.form_runner_state.TASKLIST)
              )
            %}
          {% endif %}
          {%
            do rows.append({
              "title": {
                "text": form.title,
              },
              "status": {
                "html": tasklistSectionStatusTag(submission.get_tasklist_status_for_form(form)),
              },
              "hint": {
                "html": hint_html,
              } if hint_html else {},
              "href": link_href,
            })
          %}
        {% endfor %}

        {{
          govukTaskList({
            "idPrefix": submission.collection.slug,
            "items": rows
          })
        }}
      {% endif %}
    </div>
  </div>
  {% set default_before_submission %}
    <p class="govuk-body">You must complete all sections before you can submit.</p>
  {% endset %}
  {% if runner.can_edit %}
    <div class="govuk-grid-row">
      <div class="govuk-grid-column-two-thirds">
        {{ before_submission or default_before_submission }}
        <form method="post" novalidate>
          {{ runner.tasklist_form.csrf_token }}

          {{
            runner.tasklist_form.submit(params={
              "text": submit_text or "Submit",
              "disabled": not submission.all_needed_forms_are_completed
            })
          }}
        </form>
      </div>
    </div>
  {% endif %}
{% endmacro %}

{% macro collection_add_another_summary(runner) %}
  {% set add_another_container = runner.component.add_another_container %}

  <span class="govuk-caption-l">{{ runner.component.form.title }}</span>
  <h1 class="govuk-heading-l">{{ add_another_container.name }}</h1>

  {{ runner.interpolate(add_another_container.add_another_guidance_body) | govuk_markdown }}

  {% set number_of_entries = runner.submission.get_count_for_add_another(add_another_container) %}

  {% if number_of_entries %}
    <h2 class="govuk-heading-s">You have added {{ number_of_entries }} {{ add_another_container.name | lower }}</h2>

    {% set rows = [] %}
    {% for i in range(number_of_entries) %}
      {% set (summary, is_answered) = runner.submission.get_answer_summary_for_add_another(add_another_container, add_another_index=i) %}


      {% set key_html %}
        {% if is_answered %}
          <span>{{ summary }}</span>
        {% else %}
          <a class="govuk-link govuk-link--no-visited-state" href="{{ runner.to_url(enum.form_runner_state.QUESTION, question=runner.questions[0], add_another_index=i) }}">
            Enter missing information for {{ to_ordinal(i + 1) }} {{ add_another_container.name | lower }} {{ "(" ~ summary ~ ")" if summary else "" }}
          </a>
        {% endif %}
      {% endset %}

      {% set entry_hidden_description = summary if is_answered else to_ordinal(i + 1) ~ " " ~ (add_another_container.name | lower) %}
      {% set actions = [] %}
      {% if is_answered %}
        {%
          do actions.append({
            "href": runner.to_url(enum.form_runner_state.QUESTION, question=runner.questions[0], add_another_index=i),
            "text": "Change",
            "visuallyHiddenText": entry_hidden_description,
            "classes": "govuk-link--no-visited-state"
          })
        %}
      {% endif %}
      {%
        do actions.append({
          "href": runner.to_url(enum.form_runner_state.QUESTION, question=runner.questions[0], add_another_index=i, action="remove"),
          "text": "Remove",
          "visuallyHiddenText": entry_hidden_description,
          "classes": "govuk-link--no-visited-state"
        })
      %}
      {%
        do rows.append({
          "key": { "html": key_html, "classes": "govuk-!-width-two-thirds" },
          "value": { "classes": "govuk-!-display-none"},
          "actions": {
            "items": actions,
            "classes": "govuk-!-width-one-third"
          }
        })
      %}
    {% endfor %}

    {{ govukSummaryList({ "rows": rows, "classes": "app-tasklist-builder" }) }}

    <form method="post" novalidate>
      {{ runner.add_another_summary_form.csrf_token }}

      {{
        runner.add_another_summary_form.add_another(params={
          "fieldset": {
            "legend": {
              "text": "Do you need to add another answer?",
              "isPageHeading": false,
              "classes": "govuk-fieldset__legend--m"
            }
          }
        })
      }}

      {{ runner.add_another_summary_form.submit }}
    </form>
  {% else %}
    <p class="govuk-body">You have not added any {{ add_another_container.name | lower }}.</p>

    <form method="post" novalidate>
      {{ runner.add_another_summary_form.csrf_token }}
      {{
        runner.add_another_summary_form.add_another(params={
          "fieldset": {},
          "classes": "govuk-!-display-none",
          "value": "yes"
        })
      }}
      {{
        runner.add_another_summary_form.submit(params={
          "text": "Add the first answer",
          "classes": "govuk-!-margin-top-3"
        })
      }}
    </form>
  {% endif %}
{% endmacro %}

{% macro collection_add_another_confirm_remove(runner) %}
  {% set add_another_container = runner.component.add_another_container %}
  {% set (summary, is_answered) = runner.submission.get_answer_summary_for_add_another(add_another_container, add_another_index=runner.add_another_index) %}

  {# todo: tweak how the summary works so that its only generated if the #}
  {#       form designer has explicitly select which answers should be included #}
  {#       otherwise everything should default to "answer" by default #}
  {% set heading = "Are you sure you want to remove " ~ (summary or ('answer ' ~ (runner.add_another_index + 1))) ~ "?" %}
  <span class="govuk-caption-l">{{ runner.component.add_another_container.name }}</span>

  <form method="post" novalidate>
    {{ runner.confirm_remove_form.csrf_token }}

    {{
      runner.confirm_remove_form.confirm_remove(params={
        "fieldset": {
          "legend": {
            "text": heading,
            "isPageHeading": true,
            "classes": "govuk-fieldset__legend--l"
          }
        }
      })
    }}

    {{ runner.confirm_remove_form.submit }}
  </form>
{% endmacro %}

{% macro collection_question_confirm_remove(runner) %}
  {% set question = runner.linked_question %}
  {% set existing_file_upload_answer = runner.submission.cached_get_answer_for_question(question.id, add_another_index=runner.add_another_index if runner.add_another_index is not none else none) %}

  <h1 class="govuk-heading-l">Remove your file</h1>

  {{
    govukInsetText({
      "text": existing_file_upload_answer.filename
    })
  }}

  <form method="post" novalidate>
    {{ runner.confirm_remove_form.csrf_token }}

    {{
      runner.confirm_remove_form.confirm_remove(params={
        "fieldset": {
          "legend": {
            "text": "Are you sure you want to remove your file?",
            "isPageHeading": false,
            "classes": "govuk-fieldset__legend--m"
          }
        }
      })
    }}

    {{ runner.confirm_remove_form.submit }}
  </form>
{% endmacro %}
