{% extends "modern/base.html" %}

{% block title %}Workflow Details - BLOOM LIMS{% endblock %}

{% block extra_css %}
<!-- Bootstrap 5 CSS -->
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" rel="stylesheet">
<style>
    :root {
        --wf-surface-0: var(--color-gray-900);
        --wf-surface-1: var(--color-gray-800);
        --wf-surface-2: var(--color-gray-700);
        --wf-surface-3: var(--color-gray-600);
        --wf-border: #4a5567;
        --wf-text-primary: #eef2f7;
        --wf-text-secondary: #c8d0dc;
        --wf-text-muted: #a8b2c2;
        --wf-chip-bg: #273142;
        --wf-chip-border: #5a6b82;
    }

    /* Bootstrap overrides to match BLOOM design system */
    .accordion {
        --bs-accordion-bg: var(--wf-surface-1);
        --bs-accordion-border-color: var(--wf-border);
        --bs-accordion-btn-bg: var(--wf-surface-2);
        --bs-accordion-btn-color: var(--wf-text-primary);
        --bs-accordion-active-bg: #3b4656;
        --bs-accordion-active-color: var(--wf-text-primary);
        --bs-accordion-btn-focus-box-shadow: none;
    }
    .accordion-item {
        background-color: var(--wf-surface-1);
        border-color: var(--wf-border);
    }
    .accordion-body {
        background-color: var(--wf-surface-1);
        color: var(--wf-text-secondary);
    }
    .accordion-button {
        background-color: var(--wf-surface-2);
        color: var(--wf-text-primary);
    }
    .accordion-button::after {
        filter: invert(1);
    }
    .accordion-button:not(.collapsed)::after {
        filter: invert(1);
    }
    .card {
        background-color: var(--wf-surface-1);
        border-color: var(--wf-border);
        color: var(--wf-text-secondary);
    }
    .card-header {
        background-color: var(--wf-surface-2);
        border-color: var(--wf-border);
        color: var(--wf-text-primary);
    }
    .card-body {
        background-color: var(--wf-surface-1);
    }
    .badge.bg-success { background-color: var(--color-success) !important; }
    .badge.bg-warning { background-color: var(--color-warning) !important; }
    .badge.bg-danger { background-color: var(--color-error) !important; }
    .badge.bg-info { background-color: var(--color-info) !important; }
    .badge.bg-secondary { background-color: var(--color-gray-600) !important; }
    .badge.bg-primary { background-color: var(--color-highlight) !important; }

    .workflow-header {
        display: flex;
        justify-content: space-between;
        align-items: flex-start;
        flex-wrap: wrap;
        gap: 1rem;
        margin-bottom: 1.5rem;
    }
    .workflow-meta {
        display: flex;
        flex-wrap: wrap;
        gap: 1rem;
        margin-top: 0.5rem;
    }
    .workflow-meta .badge {
        font-size: 0.875rem;
        padding: 0.5rem 0.75rem;
    }
    .accordion-button:not(.collapsed) {
        background-color: #3b4656;
        color: var(--wf-text-primary);
    }
    .accordion-button:focus {
        box-shadow: none;
        border-color: var(--wf-border);
    }
    .accordion-button.step-type-workflow_step_instance,
    .accordion-button.step-type-workflow_instance {
        background: var(--wf-surface-2);
        color: var(--wf-text-primary);
    }
    .accordion-button.step-type-plate,
    .accordion-button.step-type-rack {
        background: #3f4b5f;
        color: var(--wf-text-primary);
    }
    .accordion-button.step-type-package {
        background: #45546b;
        color: var(--wf-text-primary);
    }
    .step-info {
        display: flex;
        flex-wrap: wrap;
        gap: 0.5rem;
        align-items: center;
    }
    .step-type-badge {
        font-size: 0.75rem;
        padding: 0.25rem 0.5rem;
        background: #515f74;
        border-radius: var(--radius-sm);
        color: var(--wf-text-primary);
    }
    .descendant-summary-chips {
        display: inline-flex;
        flex-wrap: wrap;
        gap: 0.35rem;
        align-items: center;
    }
    .descendant-chip {
        display: inline-flex;
        align-items: center;
        gap: 0.35rem;
        padding: 0.18rem 0.5rem;
        border-radius: 999px;
        border: 1px solid var(--wf-chip-border);
        background: var(--wf-chip-bg);
        color: var(--wf-text-primary);
        font-size: 0.72rem;
        line-height: 1.1;
        white-space: nowrap;
        font-weight: 600;
    }
    .descendant-chip i {
        font-size: 0.72rem;
        opacity: 0.9;
    }
    .descendant-chip .chip-count {
        font-weight: 700;
    }
    .descendant-chip .chip-label {
        opacity: 0.95;
    }
    .descendant-chip.total {
        background: #2d3b4f;
        border-color: #7186a4;
    }
    .descendant-chip.category-container { border-color: #6f8faf; }
    .descendant-chip.category-content { border-color: #83a77a; }
    .descendant-chip.category-workflow { border-color: #9f8bb9; }
    .descendant-chip.category-workflow_step { border-color: #8ba3c5; }
    .descendant-chip.category-other { border-color: #7f8799; }
    .descendant-chip:hover {
        background: #32445d;
    }
    .step-links {
        display: flex;
        gap: 0.25rem;
        margin-left: auto;
        padding-right: 1rem;
        z-index: 10;
    }
    .step-links a {
        color: #b7d8ff;
        text-decoration: none;
        padding: 0.25rem 0.5rem;
        background: var(--wf-surface-0);
        border-radius: var(--radius-sm);
        font-size: 0.875rem;
        border: 1px solid var(--wf-border);
    }
    .step-links a:hover {
        color: var(--wf-text-primary);
        background: #3d4b60;
    }
    .accordion-header {
        display: flex;
        align-items: center;
    }
    .accordion-header .accordion-button {
        flex: 1;
    }
    .child-containers {
        background: var(--color-gray-700);
        border-radius: var(--radius-sm);
        padding: 0.75rem;
        margin-top: 0.5rem;
    }
    .child-containers-header {
        display: flex;
        justify-content: space-between;
        align-items: center;
        margin-bottom: 0.5rem;
    }
    .child-containers-title {
        font-weight: 600;
        color: var(--color-gray-300);
        font-size: 0.875rem;
    }
    .child-container-item {
        display: flex;
        align-items: center;
        gap: 0.5rem;
        padding: 0.5rem;
        background: var(--color-gray-800);
        border-radius: var(--radius-sm);
        margin-bottom: 0.25rem;
    }
    .child-container-item:last-child {
        margin-bottom: 0;
    }
    .child-container-type {
        font-size: 0.75rem;
        padding: 0.125rem 0.375rem;
        background: var(--color-gray-600);
        border-radius: var(--radius-sm);
        color: var(--color-gray-300);
    }
    .child-container-euid {
        color: var(--color-highlight);
        text-decoration: none;
    }
    .child-container-euid:hover {
        color: var(--color-white);
    }
    .show-children-btn {
        font-size: 0.75rem;
        padding: 0.25rem 0.5rem;
        background: var(--color-gray-600);
        border: none;
        border-radius: var(--radius-sm);
        color: var(--color-gray-200);
        cursor: pointer;
    }
    .show-children-btn:hover {
        background: var(--color-highlight);
        color: white;
    }
    /* Child Contents Styles */
    .child-contents {
        background: var(--color-gray-700);
        border-radius: var(--radius-sm);
        padding: 0.75rem;
        margin-top: 0.5rem;
        border-left: 3px solid var(--color-success);
    }
    .child-contents-header {
        display: flex;
        justify-content: space-between;
        align-items: center;
        margin-bottom: 0.5rem;
    }
    .child-contents-title {
        font-weight: 600;
        color: var(--color-gray-300);
        font-size: 0.875rem;
    }
    .child-content-item {
        display: flex;
        align-items: center;
        gap: 0.5rem;
        padding: 0.5rem;
        padding-left: 2rem;  /* Indent under container */
        background: var(--color-gray-800);
        border-radius: var(--radius-sm);
        margin-bottom: 0.25rem;
        border-left: 3px solid var(--color-success);
        margin-left: 1rem;  /* Additional left margin for nesting */
    }
    .child-content-type {
        font-size: 0.75rem;
        padding: 0.125rem 0.375rem;
        background: var(--color-success);
        border-radius: var(--radius-sm);
        color: white;
    }
    .child-content-euid {
        color: var(--color-highlight);
        text-decoration: none;
    }
    .child-content-euid:hover {
        color: var(--color-white);
    }
    .content-meta {
        font-size: 0.75rem;
        color: var(--color-gray-400);
        display: flex;
        gap: 0.5rem;
    }
    .content-meta-item {
        display: flex;
        align-items: center;
        gap: 0.25rem;
    }
    /* Override btn-outline for better visibility in accordion body */
    .accordion-body .btn-outline {
        color: var(--color-highlight);
        border-color: var(--color-highlight);
    }
    .accordion-body .btn-outline:hover {
        background: var(--color-highlight);
        color: var(--color-white);
    }
    .action-group {
        display: flex;
        flex-wrap: wrap;
        gap: 0.5rem;
        padding: 0.75rem;
        background: var(--color-gray-800);
        border-radius: var(--radius-sm);
        margin-bottom: 0.5rem;
    }
    .action-group-name {
        width: 100%;
        font-weight: 600;
        color: var(--color-gray-300);
        margin-bottom: 0.25rem;
        font-size: 0.875rem;
    }
    .action-btn {
        padding: 0.375rem 0.75rem;
        font-size: 0.875rem;
        border-radius: var(--radius-sm);
        background: var(--color-highlight);
        color: white;
        border: none;
        cursor: pointer;
        transition: all 0.2s ease;
    }
    .action-btn:hover:not(:disabled) {
        background: #4f46e5;
    }
    .action-btn:disabled {
        opacity: 0.5;
        cursor: not-allowed;
    }
    .action-form {
        background: var(--color-gray-700);
        padding: 1rem;
        border-radius: var(--radius-sm);
        margin-top: 0.5rem;
    }
    .action-form input[type="text"] {
        background: var(--color-gray-800);
        border: 1px solid var(--color-gray-600);
        color: var(--color-white);
        padding: 0.375rem 0.75rem;
        border-radius: var(--radius-sm);
        width: 100%;
    }
    /* Dynamic action forms created by action_buttons.js */
    .action-group > div[id*="-form"] {
        background: var(--color-gray-700);
        padding: 1rem;
        border-radius: var(--radius-sm);
        margin-top: 0.5rem;
        border: 1px solid var(--color-gray-600);
    }
    .action-group > div[id*="-form"] form {
        display: flex;
        flex-direction: column;
        gap: 0.75rem;
    }
    .action-group > div[id*="-form"] input[type="text"],
    .action-group > div[id*="-form"] textarea,
    .action-group > div[id*="-form"] select {
        background: var(--color-gray-800);
        border: 1px solid var(--color-gray-600);
        color: var(--color-white);
        padding: 0.5rem 0.75rem;
        border-radius: var(--radius-sm);
        font-size: 0.875rem;
        width: 100%;
        max-width: 400px;
    }
    .action-group > div[id*="-form"] select {
        cursor: pointer;
    }
    .action-group > div[id*="-form"] select option {
        background: var(--color-gray-800);
        color: var(--color-white);
    }
    .action-group > div[id*="-form"] textarea {
        min-height: 80px;
        resize: vertical;
    }
    .action-group > div[id*="-form"] .actionSubmit {
        background: var(--color-highlight);
        color: white;
        border: none;
        padding: 0.5rem 1rem;
        border-radius: var(--radius-sm);
        cursor: pointer;
        font-size: 0.875rem;
        margin-top: 0.5rem;
        width: fit-content;
    }
    .action-group > div[id*="-form"] .actionSubmit:hover {
        background: #4f46e5;
    }
    .properties-form {
        background: var(--color-gray-700);
        padding: 1rem;
        border-radius: var(--radius-sm);
        margin-top: 0.5rem;
    }
    .properties-form .form-group {
        margin-bottom: 0.75rem;
    }
    .properties-form label {
        font-size: 0.875rem;
        color: var(--color-gray-300);
        margin-bottom: 0.25rem;
        display: block;
    }
    .fedex-info {
        background: var(--color-info);
        color: white;
        padding: 0.25rem 0.5rem;
        border-radius: var(--radius-sm);
        font-size: 0.75rem;
        margin-left: 0.5rem;
    }
    .floating-controls {
        position: fixed;
        bottom: 2rem;
        right: 2rem;
        display: flex;
        flex-direction: column;
        gap: 0.5rem;
        z-index: 1000;
    }
    .floating-btn {
        width: 48px;
        height: 48px;
        border-radius: 50%;
        border: none;
        background: var(--color-highlight);
        color: white;
        font-size: 1.25rem;
        cursor: pointer;
        box-shadow: 0 4px 12px rgba(0,0,0,0.3);
        transition: all 0.2s ease;
    }
    .floating-btn:hover {
        transform: scale(1.1);
        background: #4f46e5;
    }
    .nested-steps {
        margin-left: 1.5rem;
        border-left: 2px solid var(--color-gray-600);
        padding-left: 1rem;
    }
</style>
{% endblock %}

{% block content %}
<!-- Workflow Header -->
<div class="page-header">
    <div>
        <h1>
            <a href="/euid_details?euid={{ workflow.euid }}" class="text-highlight">{{ workflow.euid }}</a>:
            {{ workflow.json_addl.get('properties', {}).get('name', 'Unnamed Workflow') }}
        </h1>
        <div class="workflow-meta">
            <span class="badge bg-{{ 'success' if workflow.bstatus == 'active' else 'secondary' }}">
                <i class="fas fa-circle"></i> {{ workflow.bstatus }}
            </span>
            <span class="badge bg-info">
                <i class="fas fa-tag"></i> {{ workflow.type }} :: {{ workflow.subtype }} :: {{ workflow.version }}
            </span>
            <span class="badge bg-secondary">
                <i class="fas fa-clock"></i> {{ workflow.created_dt | format_dt('standard') if workflow.created_dt else 'N/A' }}
            </span>
        </div>
    </div>
    <div class="page-actions">
        <button id="toggleFilterBtn" class="btn btn-outline btn-sm" title="Toggle minimal recursion">
            <i class="fas fa-filter"></i> Filter: {{ udat.get('wf_filter', 'off') }}
        </button>
        <a href="/dindex2?start_euid={{ workflow.euid }}" target="bloom_dag" class="btn btn-outline btn-sm" title="View DAG">
            <i class="fas fa-project-diagram"></i> DAG
        </a>
    </div>
</div>

<!-- Workflow Action Groups -->
{% set workflow_action_groups = action_groups_by_euid.get(workflow.euid, {}) if action_groups_by_euid is defined else {} %}
{% if workflow_action_groups %}
<div class="card mb-4">
    <div class="card-header">
        <h3 class="card-title"><i class="fas fa-play-circle"></i> Workflow Actions</h3>
    </div>
    <div class="card-body">
        {% for group_key, group_value in workflow_action_groups.items() %}
        <div class="action-group">
            <div class="action-group-name">{{ group_value.group_name }}</div>
            {% for action_key, action_value in group_value.actions.items() %}
            <button class="action-btn"
                    data-action-json="{{ action_value | tojson | e }}"
                    data-euid="{{ workflow.euid }}"
                    data-action-name="{{ action_key }}"
                    data-action-group="{{ group_key }}"
                    onclick="showCapturedDataFormFromDataAttributes(this)"
                    {% if action_value.action_enabled == "0" %}disabled{% endif %}>
                {{ action_value.action_name }}
            </button>
            {% endfor %}
        </div>
        {% endfor %}
    </div>
</div>
{% endif %}

<!-- Linked Test Requisitions (shown if workflow is child of any test_requisition) -->
{% if workflow.child_of_lineages %}
{% set linked_requisitions = [] %}
{% for lineage in workflow.child_of_lineages %}
    {% if lineage.parent_instance and lineage.parent_instance.type == 'test_requisition' and not lineage.parent_instance.is_deleted %}
        {% set _ = linked_requisitions.append(lineage.parent_instance) %}
    {% endif %}
{% endfor %}
{% if linked_requisitions|length > 0 %}
<div class="card mb-4">
    <div class="card-header">
        <h3 class="card-title"><i class="fas fa-file-medical"></i> Linked Test Requisitions ({{ linked_requisitions|length }})</h3>
    </div>
    <div class="card-body">
        {% for trx in linked_requisitions %}
        <div class="requisition-item" style="margin-bottom: var(--spacing-md); padding: var(--spacing-sm); background: var(--color-gray-700); border-radius: var(--radius-sm);">
            <div style="display: flex; align-items: center; gap: var(--spacing-sm); flex-wrap: wrap; margin-bottom: var(--spacing-sm);">
                <a href="/euid_details?euid={{ trx.euid }}" class="text-highlight" style="font-weight: 600;">{{ trx.euid }}</a>
                <span class="text-muted">{{ trx.json_addl.get('properties', {}).get('name', '') }}</span>
                <span class="badge bg-{{ 'success' if trx.bstatus == 'active' else 'secondary' }}">{{ trx.bstatus }}</span>
                <a href="/dindex2?start_euid={{ trx.euid }}" target="bloom_dag" title="View DAG" style="color: var(--color-highlight);">🕸️</a>
            </div>
            {% set trx_action_groups = action_groups_by_euid.get(trx.euid, {}) if action_groups_by_euid is defined else {} %}
            {% if trx_action_groups %}
            <div class="requisition-actions" style="display: flex; flex-wrap: wrap; gap: var(--spacing-xs);">
                {% for group_key, group_value in trx_action_groups.items() %}
                <div class="action-group" style="display: flex; align-items: center; gap: var(--spacing-xs);">
                    <span class="action-group-name" style="font-size: 0.75rem; color: var(--color-gray-400);">{{ group_value.group_name }}:</span>
                    {% for action_key, action_value in group_value.actions.items() %}
                    <button class="action-btn btn btn-outline btn-sm"
                            data-action-json="{{ action_value | tojson | e }}"
                            data-euid="{{ trx.euid }}"
                            data-action-name="{{ action_key }}"
                            data-action-group="{{ group_key }}"
                            onclick="showCapturedDataFormFromDataAttributes(this)"
                            {% if action_value.action_enabled == "0" %}disabled style="opacity: 0.5;"{% endif %}>
                        {{ action_value.action_name }}
                    </button>
                    {% endfor %}
                </div>
                {% endfor %}
            </div>
            {% endif %}
        </div>
        {% endfor %}
    </div>
</div>
{% endif %}
{% endif %}

<!-- Define recursive step rendering macro -->
{% macro render_step(step, accordion_states, step_descendant_summaries, depth=0) %}
{% set is_workflow_step = step.polymorphic_discriminator in ['workflow_step_instance', 'workflow_instance'] %}
{% set step_type = step.type %}
{% set step_id = "step-" ~ step.euid %}
{% set is_open = accordion_states.get(step.euid, 'closed') == 'open' %}
{% set descendant_summary = step_descendant_summaries.get(step.euid, {"total_descendants": 0, "counts_by_category": {}, "counts_by_type": {}}) if step_descendant_summaries is defined else {"total_descendants": 0, "counts_by_category": {}, "counts_by_type": {}} %}
{% set type_breakdown = [] %}
{% for child_type, child_count in descendant_summary.counts_by_type|dictsort(false, 'value')|reverse %}
{% set _ = type_breakdown.append(child_type ~ ': ' ~ child_count) %}
{% endfor %}
{% set type_breakdown_title = type_breakdown|join(' | ') %}

{# Separate workflow step children from container and content children #}
{# Query both container_instance AND content_instance lineages per Rule 6 (polymorphic identity naming) #}
{% set workflow_children = [] %}
{% set container_children = [] %}
{% set content_children = [] %}
{% if step.parent_of_lineages %}
    {% for child_lineage in step.get_sorted_parent_of_lineages(['container_instance', 'content_instance']) %}
        {% set child = child_lineage.child_instance %}
        {% if child.category == 'workflow_step' %}
            {% set _ = workflow_children.append(child) %}
        {% elif child.category == 'content' %}
            {% set _ = content_children.append(child) %}
        {% else %}
            {# container category #}
            {% set _ = container_children.append(child) %}
            {# Also collect contents FROM this container #}
            {% if child.parent_of_lineages %}
                {% for content_lineage in child.parent_of_lineages %}
                    {% set content = content_lineage.child_instance %}
                    {% if content.category == 'content' %}
                        {% set _ = content_children.append(content) %}
                    {% endif %}
                {% endfor %}
            {% endif %}
        {% endif %}
    {% endfor %}
{% endif %}

<div class="accordion mb-2" id="accordion-{{ step.euid }}">
    <div class="accordion-item">
        <h2 class="accordion-header">
            <button class="accordion-button {{ '' if is_open else 'collapsed' }} step-type-{{ step_type }}"
                    type="button"
                    data-bs-toggle="collapse"
                    data-bs-target="#{{ step_id }}"
                    aria-expanded="{{ 'true' if is_open else 'false' }}"
                    data-euid="{{ step.euid }}">
                <div class="step-info">
                    <span class="step-type-badge">{{ step_type }}</span>
                    <strong>{{ step.json_addl.get('properties', {}).get('name', 'NONAME') }}</strong>
                    <span class="badge bg-{{ 'success' if step.bstatus == 'active' else 'secondary' }} ms-2">{{ step.bstatus }}</span>
                    <span class="text-muted ms-2" style="font-size: 0.75rem;">{{ step.created_dt | format_dt('standard') if step.created_dt else '' }}</span>

                    {% if step_type == 'package' %}
                    {% set fedex_data = step.json_addl.get('properties', {}).get('fedex_tracking_data', []) %}
                    {% if fedex_data|length > 0 %}
                    <span class="fedex-info">
                        <i class="fas fa-truck"></i> {{ fedex_data[0].get('Delivery_Status', 'N/A') }}
                        - {{ ((fedex_data[0].get('Transit_Time_sec', 0) | float) / 60 / 60 / 24) | round(1) }} days
                    </span>
                    {% endif %}
                    {% endif %}

                    <span class="descendant-summary-chips ms-2" title="{{ type_breakdown_title if type_breakdown_title else 'No descendants' }}">
                        <span class="descendant-chip total" title="{{ type_breakdown_title if type_breakdown_title else 'No descendants' }}">
                            <i class="fas fa-sitemap"></i>
                            <span class="chip-count">{{ descendant_summary.total_descendants }}</span>
                            <span class="chip-label">total</span>
                        </span>
                        {% for category_name, category_count in descendant_summary.counts_by_category|dictsort(false, 'value')|reverse %}
                        <span class="descendant-chip category-{{ category_name }}" data-child-category="{{ category_name }}" title="{{ category_name }}: {{ category_count }}">
                            {% if category_name == 'container' %}
                            <i class="fas fa-box"></i>
                            {% elif category_name == 'content' %}
                            <i class="fas fa-vial"></i>
                            {% elif category_name == 'workflow' %}
                            <i class="fas fa-project-diagram"></i>
                            {% elif category_name == 'workflow_step' %}
                            <i class="fas fa-list-ol"></i>
                            {% else %}
                            <i class="fas fa-cube"></i>
                            {% endif %}
                            <span class="chip-count">{{ category_count }}</span>
                            <span class="chip-label">{{ category_name | replace('-', ' ') | replace('_', ' ') }}</span>
                        </span>
                        {% endfor %}
                    </span>
                </div>
            </button>
            <!-- Links OUTSIDE the button so they work independently -->
            <span class="step-links">
                <a href="/euid_details?euid={{ step.euid }}" title="View details">{{ step.euid }}</a>
                <a href="/dindex2?start_euid={{ step.euid }}" target="bloom_dag" title="View DAG">🕸️</a>
                {% if step_type == 'plate' or step_type == 'rack' %}
                <a href="/plate_visualization?plate_euid={{ step.euid }}" title="View plate"><i class="fas fa-th"></i></a>
                {% endif %}
            </span>
        </h2>
        <div id="{{ step_id }}" class="accordion-collapse collapse {{ 'show' if is_open else '' }}"
             data-bs-parent="#accordion-{{ step.euid }}">
            <div class="accordion-body">
                <!-- Action Groups for this step -->
                {% set step_action_groups = action_groups_by_euid.get(step.euid, {}) if action_groups_by_euid is defined else {} %}
                {% if step_action_groups %}
                <div class="mb-3">
                    {% for group_key, group_value in step_action_groups.items() %}
                    <div class="action-group">
                        <div class="action-group-name">{{ group_value.group_name }}</div>
                        {% for action_key, action_value in group_value.actions.items() %}
                        <button class="action-btn"
                                data-action-json="{{ action_value | tojson | e }}"
                                data-euid="{{ step.euid }}"
                                data-action-name="{{ action_key }}"
                                data-action-group="{{ group_key }}"
                                onclick="showCapturedDataFormFromDataAttributes(this)"
                                {% if action_value.action_enabled == "0" %}disabled{% endif %}>
                            {{ action_value.action_name }}
                        </button>
                        {% endfor %}
                    </div>
                    {% endfor %}
                </div>
                {% endif %}

                <!-- Carrier Tracking Form (for package steps) -->
                {% if step_type == 'package' %}
                <div class="mb-3 tracking-form-section">
                    <div class="tracking-form-header" style="display: flex; align-items: center; gap: var(--spacing-sm); margin-bottom: var(--spacing-sm);">
                        <i class="fas fa-shipping-fast" style="color: var(--color-info);"></i>
                        <span style="font-weight: 600;">Carrier Tracking</span>
                    </div>
                    <div class="tracking-input-row" style="display: flex; gap: var(--spacing-sm); flex-wrap: wrap; align-items: center;">
                        <select id="carrier-{{ step.euid }}" class="form-select" style="width: 120px;">
                            <option value="FedEx" {{ 'selected' if step.json_addl.get('properties', {}).get('carrier') == 'FedEx' else '' }}>FedEx</option>
                            <option value="UPS" {{ 'selected' if step.json_addl.get('properties', {}).get('carrier') == 'UPS' else '' }}>UPS</option>
                            <option value="USPS" {{ 'selected' if step.json_addl.get('properties', {}).get('carrier') == 'USPS' else '' }}>USPS</option>
                            <option value="Other" {{ 'selected' if step.json_addl.get('properties', {}).get('carrier') == 'Other' else '' }}>Other</option>
                        </select>
                        <input type="text" id="tracking-number-{{ step.euid }}" class="form-control"
                               placeholder="Enter tracking number"
                               value="{{ step.json_addl.get('properties', {}).get('tracking_number', '') }}"
                               style="flex: 1; min-width: 200px;">
                        <button class="btn btn-primary btn-sm" onclick="lookupTracking('{{ step.euid }}')" title="Look up tracking info">
                            <i class="fas fa-search"></i> Track
                        </button>
                        <button class="btn btn-success btn-sm" onclick="saveTracking('{{ step.euid }}')" title="Save tracking info">
                            <i class="fas fa-save"></i> Save
                        </button>
                    </div>
                    {% set fedex_data = step.json_addl.get('properties', {}).get('fedex_tracking_data', []) %}
                    {% if fedex_data|length > 0 %}
                    <div class="tracking-results" style="margin-top: var(--spacing-sm); padding: var(--spacing-sm); background: var(--color-gray-700); border-radius: var(--radius-sm);">
                        <div class="tracking-summary" style="display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: var(--spacing-sm);">
                            <div><strong>Status:</strong> {{ fedex_data[0].get('status', 'N/A') }}</div>
                            <div><strong>Transit Time:</strong> {{ ((fedex_data[0].get('Transit_Time_sec', 0) | float) / 3600) | round(1) }} hours</div>
                            <div><strong>Origin:</strong> {{ fedex_data[0].get('origin_state', 'N/A') }}</div>
                            <div><strong>Ship Date:</strong> {{ fedex_data[0].get('ship_date', 'N/A') }}</div>
                            <div><strong>Delivery:</strong> {{ fedex_data[0].get('delivery_date', 'N/A') }}</div>
                        </div>
                    </div>
                    {% endif %}
                    <div id="tracking-result-{{ step.euid }}" style="display: none; margin-top: var(--spacing-sm);"></div>
                </div>
                {% endif %}

                <!-- Properties Edit Form -->
                <details class="mb-3">
                    <summary class="btn btn-outline btn-sm"><i class="fas fa-edit"></i> Edit Properties</summary>
                    <form class="properties-form" method="post" action="/update_obj_json_addl_properties">
                        <input type="hidden" name="obj_euid" value="{{ step.euid }}">
                        {% for key, value in step.json_addl.get('properties', {}).items() %}
                        <div class="form-group">
                            <label>{{ key }}</label>
                            {% if value is string %}
                            <input type="text" class="form-control" name="{{ key }}" value="{{ value }}">
                            {% elif value is iterable and value is not mapping %}
                            <div id="list-{{ step.euid }}-{{ key }}">
                                {% for item in value %}
                                <input type="text" class="form-control mb-1" name="{{ key }}[]" value="{{ item }}">
                                {% endfor %}
                            </div>
                            <div class="btn-group btn-group-sm mt-1">
                                <button type="button" class="btn btn-outline" onclick="addListItem('{{ step.euid }}', '{{ key }}')">
                                    <i class="fas fa-plus"></i> Add
                                </button>
                                <button type="button" class="btn btn-outline" onclick="removeListItem('{{ step.euid }}', '{{ key }}')">
                                    <i class="fas fa-minus"></i> Remove
                                </button>
                            </div>
                            {% else %}
                            <input type="text" class="form-control" name="{{ key }}" value="{{ value }}">
                            {% endif %}
                        </div>
                        {% endfor %}
                        <button type="submit" class="btn btn-primary btn-sm mt-2">
                            <i class="fas fa-save"></i> Save Changes
                        </button>
                    </form>
                </details>

                <!-- Child Containers with nested Contents (collapsible) -->
                {% if container_children|length > 0 %}
                <div class="child-containers" id="containers-{{ step.euid }}">
                    <div class="child-containers-header">
                        <span class="child-containers-title">
                            <i class="fas fa-box"></i> Linked Containers ({{ container_children|length }})
                            {% if content_children|length > 0 %}
                            <span class="badge bg-success ms-1" title="Total contents">🧪 {{ content_children|length }}</span>
                            {% endif %}
                        </span>
                        <button class="show-children-btn" onclick="toggleChildContainers('{{ step.euid }}')" data-expanded="false">
                            <i class="fas fa-chevron-down"></i> Show All
                        </button>
                    </div>
                    <div class="child-container-list" id="container-list-{{ step.euid }}" style="display: none;">
                        {% for container in container_children %}
                        <div class="child-container-item" data-child-euid="{{ container.euid }}">
                            <span class="child-container-type">{{ container.type }}</span>
                            <a href="/euid_details?euid={{ container.euid }}" class="child-container-euid">{{ container.euid }}</a>
                            <span class="text-muted" style="font-size: 0.75rem;">{{ container.json_addl.get('properties', {}).get('name', '') }}</span>
                            <a href="/dindex2?start_euid={{ container.euid }}" target="bloom_dag" class="ms-auto" title="View DAG" style="color: var(--color-highlight);">🕸️</a>
                            {% if container.type == 'plate' or container.type == 'rack' %}
                            <a href="/plate_visualization?plate_euid={{ container.euid }}" title="View plate" style="color: var(--color-highlight);"><i class="fas fa-th"></i></a>
                            {% endif %}
                        </div>
                        {# Show contents nested under this container #}
                        {% if container.parent_of_lineages %}
                        {% for content_lineage in container.parent_of_lineages %}
                        {% set content = content_lineage.child_instance %}
                        {% if content.category == 'content' %}
                        <div class="child-content-item" data-child-euid="{{ content.euid }}">
                            <span class="child-content-type">{{ content.type }}</span>
                            <a href="/euid_details?euid={{ content.euid }}" class="child-content-euid">{{ content.euid }}</a>
                            <span class="text-muted" style="font-size: 0.75rem;">{{ content.json_addl.get('properties', {}).get('name', '') }}</span>
                            <span class="content-meta">
                                {% if content.json_addl.get('properties', {}).get('volume') %}
                                <span class="content-meta-item" title="Volume">
                                    <i class="fas fa-tint"></i> {{ content.json_addl.get('properties', {}).get('volume') }}
                                </span>
                                {% endif %}
                                {% if content.json_addl.get('properties', {}).get('concentration') %}
                                <span class="content-meta-item" title="Concentration">
                                    <i class="fas fa-flask"></i> {{ content.json_addl.get('properties', {}).get('concentration') }}
                                </span>
                                {% endif %}
                            </span>
                            <a href="/dindex2?start_euid={{ content.euid }}" target="bloom_dag" class="ms-auto" title="View DAG" style="color: var(--color-highlight);">🕸️</a>
                        </div>
                        {% endif %}
                        {% endfor %}
                        {% endif %}
                        {% endfor %}
                    </div>
                </div>
                {% endif %}

                <!-- Child Workflow Steps (Recursive - always shown) -->
                {% if workflow_children|length > 0 %}
                <div class="nested-steps">
                    {% for child_step in workflow_children %}
                    {{ render_step(child_step, accordion_states, step_descendant_summaries, depth + 1) }}
                    {% endfor %}
                </div>
                {% endif %}
            </div>
        </div>
    </div>
</div>
{% endmacro %}

<!-- Workflow Steps -->
<div class="card">
    <div class="card-header">
        <h3 class="card-title"><i class="fas fa-list-ol"></i> Workflow Steps</h3>
    </div>
    <div class="card-body">
        {% for step in workflow.get_sorted_parent_of_lineages(['workflow_instance']) %}
        {{ render_step(step.child_instance, accordion_states, step_descendant_summaries) }}
        {% else %}
        <p class="text-muted text-center py-4">No workflow steps found.</p>
        {% endfor %}
    </div>
</div>

<!-- Back Link -->
<div class="mt-4">
    <a href="/workflow_summary" class="btn btn-outline">
        <i class="fas fa-arrow-left"></i> Back to Workflow Summary
    </a>
</div>

<!-- Floating Controls -->
<div class="floating-controls">
    <button id="expandAllBtn" class="floating-btn" title="Expand All">
        <i class="fas fa-plus"></i>
    </button>
    <button id="collapseAllBtn" class="floating-btn" title="Collapse All">
        <i class="fas fa-minus"></i>
    </button>
</div>

{% endblock %}

{% block extra_js %}
<!-- Bootstrap 5 JS -->
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/js/bootstrap.bundle.min.js"></script>
<!-- Action Buttons (shared functionality) -->
<script src="/static/modern/js/action_buttons.js"></script>

<script>
// Fallback action handler in case cached legacy JS lacks the newer helper.
if (typeof window.showCapturedDataFormFromDataAttributes !== 'function') {
    window.showCapturedDataFormFromDataAttributes = function(button) {
        try {
            var rawActionData = button.getAttribute('data-action-json');
            if (!rawActionData) {
                throw new Error('Missing data-action-json');
            }

            var actionData;
            try {
                actionData = JSON.parse(rawActionData);
            } catch (parseError) {
                var decoder = document.createElement('textarea');
                decoder.innerHTML = rawActionData;
                actionData = JSON.parse(decoder.value);
            }

            if (typeof window.showCapturedDataForm !== 'function') {
                throw new Error('showCapturedDataForm is unavailable');
            }

            window.showCapturedDataForm(
                button,
                actionData,
                button.getAttribute('data-euid') || '',
                button.getAttribute('data-action-name') || '',
                button.getAttribute('data-action-group') || ''
            );
        } catch (error) {
            console.error('Error opening action form:', error);
            if (typeof window.BloomToast !== 'undefined' && typeof window.BloomToast.error === 'function') {
                window.BloomToast.error('Action Error', error.message || 'Unable to open action form');
            }
        }
    };
}

// Toggle child containers visibility for a step
function toggleChildContainers(stepEuid) {
    const list = document.getElementById('container-list-' + stepEuid);
    const btn = document.querySelector('#containers-' + stepEuid + ' .show-children-btn');
    if (!list || !btn) return;

    const isExpanded = btn.getAttribute('data-expanded') === 'true';
    if (isExpanded) {
        list.style.display = 'none';
        btn.innerHTML = '<i class="fas fa-chevron-down"></i> Show All';
        btn.setAttribute('data-expanded', 'false');
    } else {
        list.style.display = 'block';
        btn.innerHTML = '<i class="fas fa-chevron-up"></i> Hide';
        btn.setAttribute('data-expanded', 'true');
    }
}

// Toggle child contents visibility for a step
function toggleChildContents(stepEuid) {
    const list = document.getElementById('content-list-' + stepEuid);
    const btn = document.querySelector('#contents-' + stepEuid + ' .show-children-btn');
    if (!list || !btn) return;

    const isExpanded = btn.getAttribute('data-expanded') === 'true';
    if (isExpanded) {
        list.style.display = 'none';
        btn.innerHTML = '<i class="fas fa-chevron-down"></i> Show All';
        btn.setAttribute('data-expanded', 'false');
    } else {
        list.style.display = 'block';
        btn.innerHTML = '<i class="fas fa-chevron-up"></i> Hide';
        btn.setAttribute('data-expanded', 'true');
    }
}

// Expand all child containers and contents
function expandAllChildren() {
    // Expand containers
    document.querySelectorAll('.child-container-list').forEach(function(list) {
        list.style.display = 'block';
    });
    document.querySelectorAll('.child-containers .show-children-btn').forEach(function(btn) {
        btn.innerHTML = '<i class="fas fa-chevron-up"></i> Hide';
        btn.setAttribute('data-expanded', 'true');
    });
    // Expand contents
    document.querySelectorAll('.child-content-list').forEach(function(list) {
        list.style.display = 'block';
    });
    document.querySelectorAll('.child-contents .show-children-btn').forEach(function(btn) {
        btn.innerHTML = '<i class="fas fa-chevron-up"></i> Hide';
        btn.setAttribute('data-expanded', 'true');
    });
}

// Collapse all child containers and contents
function collapseAllChildren() {
    // Collapse containers
    document.querySelectorAll('.child-container-list').forEach(function(list) {
        list.style.display = 'none';
    });
    document.querySelectorAll('.child-containers .show-children-btn').forEach(function(btn) {
        btn.innerHTML = '<i class="fas fa-chevron-down"></i> Show All';
        btn.setAttribute('data-expanded', 'false');
    });
    // Collapse contents
    document.querySelectorAll('.child-content-list').forEach(function(list) {
        list.style.display = 'none';
    });
    document.querySelectorAll('.child-contents .show-children-btn').forEach(function(btn) {
        btn.innerHTML = '<i class="fas fa-chevron-down"></i> Show All';
        btn.setAttribute('data-expanded', 'false');
    });
}

document.addEventListener('DOMContentLoaded', function() {
    // Expand All - expands all accordions AND all child containers/contents
    document.getElementById('expandAllBtn').addEventListener('click', function() {
        // Expand all accordions
        document.querySelectorAll('.accordion-collapse').forEach(function(collapse) {
            new bootstrap.Collapse(collapse, { show: true });
        });
        document.querySelectorAll('.accordion-button').forEach(function(btn) {
            btn.classList.remove('collapsed');
            btn.setAttribute('aria-expanded', 'true');
        });
        // Expand all child containers and contents
        expandAllChildren();
    });

    // Collapse All - collapses all accordions AND all child containers/contents
    document.getElementById('collapseAllBtn').addEventListener('click', function() {
        // Collapse all accordions
        document.querySelectorAll('.accordion-collapse.show').forEach(function(collapse) {
            new bootstrap.Collapse(collapse, { hide: true });
        });
        document.querySelectorAll('.accordion-button').forEach(function(btn) {
            btn.classList.add('collapsed');
            btn.setAttribute('aria-expanded', 'false');
        });
        // Collapse all child containers and contents
        collapseAllChildren();
    });

    // Track accordion state changes
    document.querySelectorAll('.accordion-button').forEach(function(btn) {
        btn.addEventListener('click', function(e) {
            const euid = this.getAttribute('data-euid');
            const isExpanded = this.getAttribute('aria-expanded') === 'true';
            const state = isExpanded ? 'closed' : 'open'; // Will toggle

            fetch('/update_accordion_state', {
                method: 'POST',
                headers: { 'Content-Type': 'application/json' },
                body: JSON.stringify({ step_euid: euid, state: state })
            }).catch(err => console.error('Error updating accordion state:', err));
        });
    });

    // Filter Toggle
    document.getElementById('toggleFilterBtn').addEventListener('click', function() {
        const currentVal = '{{ udat.get("wf_filter", "off") }}';
        fetch('/set_filter?curr_val=' + currentVal)
            .then(response => response.json())
            .then(data => {
                this.innerHTML = '<i class="fas fa-filter"></i> Filter: ' + data.new_filter_value;
                window.location.reload();
            })
            .catch(error => console.error('Error:', error));
    });
});

// List item management for property forms
function addListItem(stepEuid, key) {
    const list = document.getElementById('list-' + stepEuid + '-' + key);
    const input = document.createElement('input');
    input.type = 'text';
    input.className = 'form-control mb-1';
    input.name = key + '[]';
    list.appendChild(input);
}

function removeListItem(stepEuid, key) {
    const list = document.getElementById('list-' + stepEuid + '-' + key);
    if (list.childElementCount > 1) {
        list.removeChild(list.lastChild);
    }
}

// Carrier Tracking Functions
function lookupTracking(stepEuid) {
    const carrier = document.getElementById('carrier-' + stepEuid).value;
    const trackingNumber = document.getElementById('tracking-number-' + stepEuid).value.trim();
    const resultDiv = document.getElementById('tracking-result-' + stepEuid);

    if (!trackingNumber) {
        resultDiv.innerHTML = '<span class="text-warning"><i class="fas fa-exclamation-triangle"></i> Please enter a tracking number</span>';
        resultDiv.style.display = 'block';
        return;
    }

    resultDiv.innerHTML = '<i class="fas fa-spinner fa-spin"></i> Looking up tracking...';
    resultDiv.style.display = 'block';

    fetch('/api/v1/tracking/track/' + encodeURIComponent(trackingNumber) + '?carrier=' + encodeURIComponent(carrier))
        .then(response => response.json())
        .then(data => {
            if (data.error) {
                resultDiv.innerHTML = '<span class="text-warning"><i class="fas fa-exclamation-triangle"></i> ' + data.error + '</span>';
            } else {
                let html = '<div class="tracking-summary" style="display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: var(--spacing-sm); padding: var(--spacing-sm); background: var(--color-gray-700); border-radius: var(--radius-sm);">';
                html += '<div><strong>Status:</strong> ' + (data.status || 'N/A') + '</div>';
                if (data.transit_time_hours) html += '<div><strong>Transit Time:</strong> ' + data.transit_time_hours + ' hours</div>';
                if (data.origin_state) html += '<div><strong>Origin:</strong> ' + data.origin_state + '</div>';
                if (data.ship_date) html += '<div><strong>Ship Date:</strong> ' + data.ship_date + '</div>';
                if (data.delivery_date) html += '<div><strong>Delivery:</strong> ' + data.delivery_date + '</div>';
                html += '</div>';
                resultDiv.innerHTML = html;
            }
        })
        .catch(error => {
            resultDiv.innerHTML = '<span class="text-warning"><i class="fas fa-exclamation-triangle"></i> Tracking lookup failed: ' + error.message + '</span>';
        });
}

function saveTracking(stepEuid) {
    const carrier = document.getElementById('carrier-' + stepEuid).value;
    const trackingNumber = document.getElementById('tracking-number-' + stepEuid).value.trim();
    const resultDiv = document.getElementById('tracking-result-' + stepEuid);

    if (!trackingNumber) {
        resultDiv.innerHTML = '<span class="text-warning"><i class="fas fa-exclamation-triangle"></i> Please enter a tracking number</span>';
        resultDiv.style.display = 'block';
        return;
    }

    resultDiv.innerHTML = '<i class="fas fa-spinner fa-spin"></i> Saving tracking info...';
    resultDiv.style.display = 'block';

    const formData = new FormData();
    formData.append('obj_euid', stepEuid);
    formData.append('carrier', carrier);
    formData.append('tracking_number', trackingNumber);

    fetch('/update_obj_json_addl_properties', {
        method: 'POST',
        body: formData
    })
    .then(response => {
        if (!response.ok) throw new Error('Failed to save');
        return response.json();
    })
    .then(data => {
        resultDiv.innerHTML = '<span class="text-success"><i class="fas fa-check"></i> Tracking information saved. Looking up details...</span>';
        // After saving, look up the tracking info
        setTimeout(() => lookupTracking(stepEuid), 500);
    })
    .catch(error => {
        resultDiv.innerHTML = '<span class="text-warning"><i class="fas fa-exclamation-triangle"></i> Failed to save: ' + error.message + '</span>';
    });
}
</script>
{% endblock %}
