{# Create workflow -#}

{% from 'macros.j2' import required with context -%}

from collections.abc import Generator

import structlog

from orchestrator.forms import FormPage
from orchestrator.forms.validators import Divider, Label, CustomerId, MigrationSummary
from orchestrator.targets import Target
from orchestrator.types import FormGenerator, State, SubscriptionLifecycle, UUIDstr
from orchestrator.workflow import StepList, begin, step
from orchestrator.workflows.steps import store_process_subscription
from orchestrator.workflows.utils import create_workflow

from {{ product_types_module }}.{{ product.variable }} import {{ product.type }}Inactive, {{ product.type }}Provisioning
{%-if validation_imports %}
from workflows.{{ product.variable }}.shared.forms import {{ validation_imports | join(", ") }}
{%-endif %}
{% if product.config.summary_forms -%}
from workflows.shared import create_summary_form
{%- endif %}

{% include 'additional_create_imports.j2' %}


logger = structlog.get_logger(__name__)


def initial_input_form_generator(product_name: str) -> FormGenerator:
    # TODO add additional fields to form if needed

    class Create{{ product.type }}Form(FormPage):
        class Config:
            title = product_name

        customer_id: CustomerId
{% include "additional_create_input_fields.j2" ignore missing %}

        label_{{ product.variable }}_settings: Label
        divider_1: Divider

        {% for field in product_block.fields -%}
        {% if field.type not in existing_product_blocks -%}
        {{ field.name }}: {{ required(field, field.type, ["inactive"]) }}{% if field.default is defined %} = {{field.default}}{% endif %}
        {%- endif %}
        {% endfor -%}

{% for validation in validations %}
        """{{ validation.validation.description }}"""
        _validate_{{ validation.validation.id }}: classmethod = {{ validation.validation.id }}_validator()
{% endfor %}

    user_input = yield Create{{ product.type }}Form
    user_input_dict = user_input.dict()
    {% if product.config.summary_forms %}
    summary_fields = [{% for field in product_block.fields %}{% if field.type not in existing_product_blocks %}"{{ field.name }}", {% endif %}{% endfor %}]
    yield from create_summary_form(user_input_dict, product_name, summary_fields)
    {%- endif %}

    return user_input_dict


@step("Construct Subscription model")
def construct_{{ product.variable }}_model(
    product: UUIDstr,
    customer_id: UUIDstr,
    {% for field in product_block.fields -%}
    {% if field.type not in existing_product_blocks -%}
    {{ field.name }}: {{ required(field, field.type, ["inactive"]) }},
    {%- endif %}
    {% endfor -%}
) -> State:
    {{ product.variable }} = {{ product.type }}Inactive.from_product_id(
        product_id=product,
        customer_id=customer_id,
        status=SubscriptionLifecycle.INITIAL,
    )

    {%- for field in product_block.fields %}
    {{ product.variable }}.{{ product_block.name }}.{{ field.name }} = {{ field.name }}
    {%- endfor %}

    {{ product.variable }} = {{ product.type }}Provisioning.from_other_lifecycle({{ product.variable }}, SubscriptionLifecycle.PROVISIONING)
    {{ product.variable }}.description = subscription_description({{ product.variable }})

    return {
        "subscription": {{ product.variable }},
        "subscription_id": {{ product.variable }}.subscription_id,  # necessary to be able to use older generic step functions
        "subscription_description": {{ product.variable }}.description,
    }


{% include 'additional_create_steps.j2' %}


@create_workflow("Create {{ product.name }}", initial_input_form=initial_input_form_generator, additional_steps=additional_steps)
def create_{{ product.variable }}() -> StepList:
    return (
        begin
        >> construct_{{ product.variable }}_model
        >> store_process_subscription(Target.CREATE)
        # TODO add provision step(s)
    )
