var updateStreamingModeOptions = window.CrankStreamingForm.updateStreamingModeOptions;
var updateStreamingConfigVisibility = window.CrankStreamingForm.updateStreamingConfigVisibility;

function buildToolDescription() {
  return {
    title: textValue('tool-title') || textValue('tool-display-name') || textValue('tool-name'),
    description: textValue('tool-description'),
    tags: [],
    examples: [],
  };
}

function collectWizardPayload() {
  var name = textValue('tool-name');
  if (!name) throw new Error(tKey('wizard.error.tool_name'));

  var inputSchemaValue = parseStructuredText(textValue('tool-input-schema'));
  var outputSchemaValue = parseStructuredText(textValue('tool-output-schema'));
  var inputMappingValue = parseStructuredText(textValue('tool-input-mapping'));
  var outputMappingValue = parseStructuredText(textValue('tool-output-mapping'));

  return {
    name: name,
    display_name: textValue('tool-display-name') || name,
    category: 'general',
    protocol: wizardProtocol,
    target: buildTarget(),
    input_schema: convertJsonSchemaToCrankSchema(inputSchemaValue, []),
    output_schema: convertJsonSchemaToCrankSchema(outputSchemaValue, []),
    input_mapping: buildMappingSet(inputMappingValue, 'input'),
    output_mapping: buildMappingSet(outputMappingValue, 'output'),
    execution_config: parseExecutionConfig(textValue('tool-exec-config')),
    tool_description: buildToolDescription(),
  };
}

async function saveOperation(stayOnPage) {
  try {
    await persistCurrentDraft(stayOnPage);
  } catch (error) {
    if (window.CrankUi) {
      window.CrankUi.error(error.message || tKey('wizard.error.save'), tKey('wizard.error.save_title'));
    }
  }
}

async function loadOperationForEdit() {
  if (!wizardWorkspaceId || !wizardEditId) return;
  var detail = await window.CrankApi.getOperation(wizardWorkspaceId, wizardEditId);
  wizardProtocol = detail.protocol || 'rest';
  await loadWizardPanels([3]);
  var draftVersion = await window.CrankApi.getOperationVersion(
    wizardWorkspaceId,
    wizardEditId,
    detail.draft_version_ref.version
  );
  wizardCurrentOperation = detail;
  wizardCurrentVersion = draftVersion;
  prefillWizardFromEdit(detail, draftVersion);
}

function setEditModePresentation() {
  var progressLabel = document.querySelector('.progress-label');
  if (progressLabel) progressLabel.textContent = tKey('wizard.progress.edit');
  renderSidebarBrand('edit');
}

function selectProtocol(protocol) {
  wizardProtocol = protocol || 'rest';
  document.querySelectorAll('.protocol-card').forEach(function(card) {
    var proto = card.dataset.protocol
      || (card.classList.contains('rest')
        ? 'rest'
        : card.classList.contains('graphql')
          ? 'graphql'
          : card.classList.contains('grpc')
            ? 'grpc'
            : card.classList.contains('websocket')
              ? 'websocket'
            : card.classList.contains('soap')
              ? 'soap'
              : 'rest');
    var selected = proto === wizardProtocol;
    card.classList.toggle('selected', selected);
    card.setAttribute('aria-checked', selected ? 'true' : 'false');
  });
  var s3name = document.getElementById('sidebar-step-3-name');
  if (s3name) {
    var step3Labels = window.CrankWizardState.step3Labels();
    s3name.textContent = step3Labels[wizardProtocol] || tKey('wizard.step3.rest.label');
  }
  updateWizardProtocolVisibility();
}

function bindWizardLiveActions() {
  bindLiveAction('wizard-upload-input-sample', tKey('wizard.busy.input_sample'), uploadInputSampleFromWizard);
  bindLiveAction('wizard-upload-output-sample', tKey('wizard.busy.output_sample'), uploadOutputSampleFromWizard);
  bindLiveAction('wizard-generate-draft', tKey('wizard.busy.generate'), generateDraftFromWizard);
  bindLiveAction('wizard-run-test', tKey('wizard.busy.test'), runWizardTest);
  bindClick('wizard-copy-test-response', copyTestResponseToOutputSample);
  bindLiveAction('wizard-export-yaml', tKey('wizard.busy.export_yaml'), exportWizardYaml);
  bindLiveAction('wizard-import-yaml', tKey('wizard.busy.import_yaml'), importWizardYaml);
  bindLiveAction('wizard-publish-operation', tKey('wizard.busy.publish'), publishWizardOperation);
  bindClick('wizard-select-descriptor-set', function() {
    var input = document.getElementById('wizard-descriptor-set-input');
    if (input) input.click();
  });
  bindLiveAction('wizard-upload-descriptor-set', tKey('wizard.busy.descriptor'), uploadDescriptorSetAndDiscover);
  bindClick('wizard-select-soap-wsdl', function() {
    var input = document.getElementById('wizard-soap-wsdl-input');
    if (input) input.click();
  });
  bindClick('wizard-select-soap-xsd', function() {
    var input = document.getElementById('wizard-soap-xsd-input');
    if (input) input.click();
  });
  bindLiveAction('wizard-upload-soap-contracts', tKey('wizard.busy.wsdl'), uploadSoapArtifactsAndInspect);
  bindClick('wizard-import-yaml-file-trigger', function() {
    var input = document.getElementById('wizard-import-yaml-file');
    if (input) input.click();
  });

  var descriptorInput = document.getElementById('wizard-descriptor-set-input');
  if (descriptorInput) descriptorInput.addEventListener('change', handleDescriptorSetSelection);
  var soapWsdlInput = document.getElementById('wizard-soap-wsdl-input');
  if (soapWsdlInput) soapWsdlInput.addEventListener('change', handleSoapWsdlSelection);
  var soapXsdInput = document.getElementById('wizard-soap-xsd-input');
  if (soapXsdInput) soapXsdInput.addEventListener('change', handleSoapXsdSelection);

  var yamlInput = document.getElementById('wizard-import-yaml-file');
  if (yamlInput) yamlInput.addEventListener('change', handleImportYamlFileSelection);
}

function bindClick(id, handler) {
  var element = document.getElementById(id);
  if (!element) return;
  element.addEventListener('click', function(event) {
    event.preventDefault();
    handler();
  });
}

function bindLiveAction(id, busyLabel, handler) {
  var element = document.getElementById(id);
  if (!element) return;
  element.addEventListener('click', function(event) {
    event.preventDefault();
    runWizardLiveAction(element, busyLabel, handler);
  });
}

async function runWizardLiveAction(button, busyLabel, handler) {
  if (!button || button.dataset.busy === 'true') {
    return;
  }

  var originalLabel = button.textContent;
  button.dataset.busy = 'true';
  button.disabled = true;
  button.classList.add('is-busy');
  button.textContent = busyLabel;

  try {
    await handler();
  } catch (error) {
    showWizardLiveStatus(
      tKey('wizard.live.failed_title'),
      error && error.message ? error.message : tKey('wizard.live.failed_body'),
      true
    );
    if (window.CrankUi) {
      window.CrankUi.error(
        error && error.message ? error.message : tKey('wizard.live.failed_body'),
        tKey('wizard.live.failed_title')
      );
    }
  } finally {
    button.dataset.busy = 'false';
    button.disabled = false;
    button.classList.remove('is-busy');
    button.textContent = originalLabel;
  }
}

function updateWizardProtocolVisibility() {
  var grpcTools = document.getElementById('wizard-grpc-live-tools');
  if (grpcTools) grpcTools.hidden = wizardProtocol !== 'grpc';
  updateStreamingModeOptions();
  updateStreamingConfigVisibility();
  if (typeof window.renderEditionCapabilityHints === 'function'
      && window.CrankWizardState
      && typeof window.CrankWizardState.currentEditionCapabilities === 'function') {
    window.renderEditionCapabilityHints(window.CrankWizardState.currentEditionCapabilities());
  }
}

function showWizardLiveStatus(title, text, isError) {
  var root = document.getElementById('wizard-live-status');
  var titleEl = document.getElementById('wizard-live-status-title');
  var textEl = document.getElementById('wizard-live-status-text');
  if (!root || !titleEl || !textEl) return;
  titleEl.textContent = title;
  textEl.textContent = text;
  root.hidden = false;
  root.classList.toggle('is-error', !!isError);
  root.classList.toggle('is-success', !isError);
}

function currentDraftVersion() {
  if (wizardCurrentOperation && wizardCurrentOperation.draft_version_ref) {
    return wizardCurrentOperation.draft_version_ref.version;
  }
  if (wizardCurrentOperation && wizardCurrentOperation.current_draft_version) {
    return wizardCurrentOperation.current_draft_version;
  }
  if (wizardCurrentVersion && wizardCurrentVersion.version) {
    return wizardCurrentVersion.version;
  }
  return 1;
}

function updateOperationPayload(payload) {
  return {
    display_name: payload.display_name,
    category: payload.category,
    target: payload.target,
    input_schema: payload.input_schema,
    output_schema: payload.output_schema,
    input_mapping: payload.input_mapping,
    output_mapping: payload.output_mapping,
    execution_config: payload.execution_config,
    tool_description: payload.tool_description,
  };
}

async function refreshCurrentOperationState() {
  if (!wizardWorkspaceId || !wizardEditId) return null;
  var detail = await window.CrankApi.getOperation(wizardWorkspaceId, wizardEditId);
  var versionNumber = detail.draft_version_ref
    ? detail.draft_version_ref.version
    : detail.current_draft_version;
  var versionDocument = await window.CrankApi.getOperationVersion(
    wizardWorkspaceId,
    wizardEditId,
    versionNumber
  );
  wizardCurrentOperation = detail;
  wizardCurrentVersion = versionDocument;
  updateWizardProtocolVisibility();
  return {
    detail: detail,
    version: versionDocument,
  };
}

async function uploadPendingGrpcArtifacts(payload) {
  if (wizardProtocol !== 'grpc' || !wizardEditId) return;

  var descriptorResponse = null;

  if (wizardProtoUpload) {
    descriptorResponse = await window.CrankApi.uploadProtoFile(
      wizardWorkspaceId,
      wizardEditId,
      new TextEncoder().encode(wizardProtoUpload.content),
      wizardProtoUpload.fileName
    );
    wizardProtoUpload = null;
  }

  if (wizardDescriptorSetUpload) {
    descriptorResponse = await window.CrankApi.uploadDescriptorSet(
      wizardWorkspaceId,
      wizardEditId,
      wizardDescriptorSetUpload.bytes,
      wizardDescriptorSetUpload.fileName
    );
    wizardDescriptorSetUpload = null;
    var descriptorName = document.getElementById('wizard-descriptor-set-name');
    if (descriptorName) descriptorName.textContent = tKey('wizard.descriptor.uploaded');
  }

  if (!descriptorResponse) return;

  payload.target.descriptor_ref = descriptorResponse.descriptor_id;
  payload.target.descriptor_set_b64 = '';
  await window.CrankApi.updateOperation(
    wizardWorkspaceId,
    wizardEditId,
    updateOperationPayload(payload)
  );
}

async function uploadPendingSoapArtifacts(payload) {
  if (wizardProtocol !== 'soap' || !wizardEditId) return;

  var wsdlResponse = null;
  if (wizardSoapWsdlUpload) {
    wsdlResponse = await window.CrankApi.uploadWsdlFile(
      wizardWorkspaceId,
      wizardEditId,
      wizardSoapWsdlUpload.bytes,
      wizardSoapWsdlUpload.fileName
    );
    wizardSoapWsdlUpload = null;
    var wsdlName = document.getElementById('wizard-soap-wsdl-name');
    if (wsdlName) wsdlName.textContent = tKey('wizard.step3.soap.wsdl_uploaded');
  }

  if (wizardSoapXsdUpload) {
    await window.CrankApi.uploadXsdFile(
      wizardWorkspaceId,
      wizardEditId,
      wizardSoapXsdUpload.bytes,
      wizardSoapXsdUpload.fileName
    );
    wizardSoapXsdUpload = null;
    var xsdName = document.getElementById('wizard-soap-xsd-name');
    if (xsdName) xsdName.textContent = tKey('wizard.step3.soap.xsd_uploaded');
  }

  if (!wsdlResponse) return;

  payload.target.wsdl_ref = wsdlResponse.descriptor_id;
  await window.CrankApi.updateOperation(
    wizardWorkspaceId,
    wizardEditId,
    updateOperationPayload(payload)
  );
}

async function persistCurrentDraft(stayOnPage) {
  if (!wizardWorkspaceId) {
    throw new Error(tKey('wizard.error.no_workspace'));
  }

  var payload = collectWizardPayload();
  var response;
  var createdNow = false;

  if (wizardMode === 'edit' && wizardEditId) {
    response = await window.CrankApi.updateOperation(
      wizardWorkspaceId,
      wizardEditId,
      updateOperationPayload(payload)
    );
  } else {
    response = await window.CrankApi.createOperation(wizardWorkspaceId, payload);
    createdNow = true;
    wizardEditId = response.operation_id;
    wizardMode = 'edit';
    history.replaceState(
      {},
      '',
      window.location.pathname + '?mode=edit&operationId=' + encodeURIComponent(wizardEditId)
    );
    setEditModePresentation();
    _doGoToStep(currentStep);
    var toolNameInput = document.getElementById('tool-name');
    if (toolNameInput) toolNameInput.disabled = true;
  }

  await uploadPendingGrpcArtifacts(payload);
  await uploadPendingSoapArtifacts(payload);
  await refreshCurrentOperationState();

  if (stayOnPage) {
    var saveDraftBtn = document.querySelector('.btn-save-draft');
    if (saveDraftBtn) {
      var label = saveDraftBtn.textContent;
      saveDraftBtn.textContent = tKey('wizard.save.saved');
      setTimeout(function() {
        saveDraftBtn.textContent = label;
      }, 1400);
    }
  }

  showWizardLiveStatus(
    createdNow ? tKey('wizard.save.created') : tKey('wizard.save.updated'),
    tKey('wizard.save.body')
  );
  return response;
}

function safeStringify(value) {
  if (value === null || value === undefined) return '';
  if (typeof value === 'string') return value;
  return JSON.stringify(value, null, 2);
}

function setTextareaValue(id, value) {
  var element = document.getElementById(id);
  if (!element) return;
  element.value = safeStringify(value);
}

function describeWizardTestResult(result) {
  if (wizardProtocol === 'websocket') {
    if (!result.ok && result.errors && result.errors.length) {
      var websocketError = result.errors[0] || {};
      var websocketMessage = websocketError.message || '';
      var websocketBody = tKey('wizard.test.websocket_failed_body');
      if (/reconnect policy exhausted/i.test(websocketMessage)) {
        websocketBody = tKey('wizard.test.websocket_failed_reconnect_body');
      } else if (/close frame before collection completed|closed before collection completed/i.test(websocketMessage)) {
        websocketBody = tKey('wizard.test.websocket_failed_closed_body');
      }
      return {
        title: tKey('wizard.test.websocket_failed'),
        body: websocketBody,
        isError: true,
      };
    }

    if (result.stream_session && result.stream_session.session_id) {
      return {
        title: tKey('wizard.test.websocket_session_started'),
        body: tfKey('wizard.test.websocket_session_started_body', {
          session_id: result.stream_session.session_id,
          poll_after_ms: result.stream_session.poll_after_ms,
        }),
        isError: false,
      };
    }

    if (result.async_job && result.async_job.job_id) {
      return {
        title: tKey('wizard.test.websocket_async_job_started'),
        body: tfKey('wizard.test.websocket_async_job_started_body', {
          job_id: result.async_job.job_id,
        }),
        isError: false,
      };
    }

    if (result.window) {
      var itemCount = Array.isArray(result.response_preview && result.response_preview.items)
        ? result.response_preview.items.length
        : 0;
      var websocketBodyParts = [
        tfKey('wizard.test.websocket_window_completed_body', { items: itemCount })
      ];
      if (result.window.truncated) {
        websocketBodyParts.push(tKey('wizard.test.websocket_window_truncated_note'));
      }
      if (result.window.has_more) {
        websocketBodyParts.push(tKey('wizard.test.websocket_window_more_note'));
      }
      if (!result.window.window_complete) {
        websocketBodyParts.push(tKey('wizard.test.websocket_window_incomplete_note'));
      }
      return {
        title: result.ok ? tKey('wizard.test.websocket_window_completed') : tKey('wizard.test.websocket_failed'),
        body: websocketBodyParts.join(' '),
        isError: !result.ok,
      };
    }
  }

  if (result.stream_session && result.stream_session.session_id) {
    return {
      title: tKey('wizard.test.session_started'),
      body: tfKey('wizard.test.session_started_body', {
        session_id: result.stream_session.session_id,
        poll_after_ms: result.stream_session.poll_after_ms
      }),
      isError: false,
    };
  }

  if (result.async_job && result.async_job.job_id) {
    return {
      title: tKey('wizard.test.async_job_started'),
      body: tfKey('wizard.test.async_job_started_body', {
        job_id: result.async_job.job_id
      }),
      isError: false,
    };
  }

  if (result.window) {
    var bodyParts = [
      tKey('wizard.test.window_completed_body')
    ];
    if (result.window.truncated) {
      bodyParts.push(tKey('wizard.test.window_truncated_note'));
    }
    if (result.window.has_more) {
      bodyParts.push(tKey('wizard.test.window_more_note'));
    }
    if (!result.window.window_complete) {
      bodyParts.push(tKey('wizard.test.window_incomplete_note'));
    }
    return {
      title: result.ok ? tKey('wizard.test.window_completed') : tKey('wizard.test.failed'),
      body: bodyParts.join(' '),
      isError: !result.ok,
    };
  }

  return {
    title: result.ok ? tKey('wizard.test.completed') : tKey('wizard.test.failed'),
    body: result.ok ? tKey('wizard.test.completed_body') : tKey('wizard.test.failed_body'),
    isError: !result.ok,
  };
}

async function uploadInputSampleFromWizard() {
  await persistCurrentDraft(true);
  await window.CrankApi.uploadInputSample(
    wizardWorkspaceId,
    wizardEditId,
    parseStructuredText(textValue('wizard-input-sample'))
  );
  showWizardLiveStatus(tKey('wizard.sample.input_saved'), tKey('wizard.sample.input_saved_body'));
}

async function uploadOutputSampleFromWizard() {
  await persistCurrentDraft(true);
  await window.CrankApi.uploadOutputSample(
    wizardWorkspaceId,
    wizardEditId,
    parseStructuredText(textValue('wizard-output-sample'))
  );
  showWizardLiveStatus(tKey('wizard.sample.output_saved'), tKey('wizard.sample.output_saved_body'));
}

async function generateDraftFromWizard() {
  await persistCurrentDraft(true);
  var generated = await window.CrankApi.generateDraft(wizardWorkspaceId, wizardEditId, {});
  setValue('tool-input-schema', JSON.stringify(crankSchemaToJsonSchema(generated.input_schema), null, 2));
  setValue('tool-output-schema', JSON.stringify(crankSchemaToJsonSchema(generated.output_schema), null, 2));
  setValue('tool-input-mapping', mappingSetToEditorValue(generated.input_mapping, 'input', wizardProtocol));
  setValue('tool-output-mapping', mappingSetToEditorValue(generated.output_mapping, 'output', wizardProtocol));
  showWizardLiveStatus(tKey('wizard.sample.generated'), tKey('wizard.sample.generated_body'));
}

async function runWizardTest() {
  await persistCurrentDraft(true);
  var result = await window.CrankApi.runOperationTest(wizardWorkspaceId, wizardEditId, {
    version: currentDraftVersion(),
    input: parseStructuredText(textValue('wizard-test-input')),
  });
  wizardTestResponsePreview = result.response_preview;
  setTextareaValue('wizard-test-request-preview', result.request_preview);
  setTextareaValue('wizard-test-response-preview', result.response_preview);
  setTextareaValue('wizard-test-errors', result.errors && result.errors.length ? result.errors : []);
  var status = describeWizardTestResult(result);
  showWizardLiveStatus(
    status.title,
    status.body,
    status.isError
  );
}

function copyTestResponseToOutputSample() {
  if (!wizardTestResponsePreview) {
    showWizardLiveStatus(tKey('wizard.test.no_response'), tKey('wizard.test.no_response_body'), true);
    return;
  }
  setTextareaValue('wizard-output-sample', wizardTestResponsePreview);
  showWizardLiveStatus(tKey('wizard.test.response_copied'), tKey('wizard.test.response_copied_body'));
}

window.CrankWizardLive = {
  saveOperation: saveOperation,
  loadOperationForEdit: loadOperationForEdit,
  bindWizardLiveActions: bindWizardLiveActions,
  updateWizardProtocolVisibility: updateWizardProtocolVisibility,
};
