/**
 * @fileoverview A reusable stepper component for guided workflows.
 * Supports step dependencies, persistence, and event-driven actions.
 */

const ICONS = {
  pending: '',
  active: `<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
    <circle cx="12" cy="12" r="10"/>
    <path d="M12 6v6l4 2"/>
  </svg>`,
  completed: `<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5">
    <polyline points="20 6 9 17 4 12"/>
  </svg>`,
  error: `<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
    <line x1="18" y1="6" x2="6" y2="18"/>
    <line x1="6" y1="6" x2="18" y2="18"/>
  </svg>`,
  skipped: `<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
    <line x1="5" y1="12" x2="19" y2="12"/>
  </svg>`
};

class DsWorkflow extends HTMLElement {
  constructor() {
    super();
    this.attachShadow({ mode: 'open' });
    this._steps = [];
  }

  static get observedAttributes() {
    return ['workflow-id'];
  }

  get workflowId() {
    return this.getAttribute('workflow-id');
  }

  set steps(stepsArray) {
    this._steps = stepsArray.map(s => ({
      status: 'pending',
      optional: false,
      dependsOn: [],
      ...s
    }));
    this._loadState();
    this._render();
  }

  get steps() {
    return this._steps;
  }

  connectedCallback() {
    this._renderBase();
  }

  _loadState() {
    if (!this.workflowId) return;
    try {
      const savedState = JSON.parse(localStorage.getItem(`dss_workflow_${this.workflowId}`));
      if (savedState) {
        this._steps.forEach(step => {
          if (savedState[step.id]) {
            step.status = savedState[step.id].status;
            if (savedState[step.id].message) {
              step.message = savedState[step.id].message;
            }
          }
        });
      }
    } catch (e) {
      console.error('Failed to load workflow state:', e);
    }
  }

  _saveState() {
    if (!this.workflowId) return;
    const stateToSave = this._steps.reduce((acc, step) => {
      acc[step.id] = {
        status: step.status,
        message: step.message || null
      };
      return acc;
    }, {});
    localStorage.setItem(`dss_workflow_${this.workflowId}`, JSON.stringify(stateToSave));
  }

  /**
   * Update a step's status
   * @param {string} stepId - The step ID
   * @param {string} status - 'pending', 'active', 'completed', 'error', 'skipped'
   * @param {string} [message] - Optional message (for error states)
   */
  updateStepStatus(stepId, status, message = '') {
    const step = this._steps.find(s => s.id === stepId);
    if (step) {
      step.status = status;
      step.message = message;
      this._saveState();
      this._render();

      this.dispatchEvent(new CustomEvent('workflow-step-change', {
        bubbles: true,
        composed: true,
        detail: { ...step }
      }));

      // Check if workflow is complete
      const requiredSteps = this._steps.filter(s => !s.optional);
      const completedRequired = requiredSteps.filter(s => s.status === 'completed').length;

      if (completedRequired === requiredSteps.length && requiredSteps.length > 0) {
        this.dispatchEvent(new CustomEvent('workflow-complete', {
          bubbles: true,
          composed: true
        }));
      }
    }
  }

  /**
   * Reset the workflow to initial state
   */
  reset() {
    this._steps.forEach(step => {
      step.status = 'pending';
      step.message = '';
    });
    this._saveState();
    this._render();
  }

  /**
   * Skip a step
   * @param {string} stepId - The step ID to skip
   */
  skipStep(stepId) {
    const step = this._steps.find(s => s.id === stepId);
    if (step && step.optional) {
      this.updateStepStatus(stepId, 'skipped');
    }
  }

  _determineActiveStep() {
    const completedIds = new Set(
      this._steps
        .filter(s => s.status === 'completed' || s.status === 'skipped')
        .map(s => s.id)
    );

    let foundActive = false;

    this._steps.forEach(step => {
      if (step.status === 'pending' && !foundActive) {
        const depsMet = (step.dependsOn || []).every(depId => completedIds.has(depId));
        if (depsMet) {
          step.status = 'active';
          foundActive = true;
        }
      }
    });
  }

  _getProgress() {
    const total = this._steps.filter(s => !s.optional).length;
    const completed = this._steps.filter(s =>
      !s.optional && (s.status === 'completed' || s.status === 'skipped')
    ).length;
    return total > 0 ? (completed / total) * 100 : 0;
  }

  _renderBase() {
    this.shadowRoot.innerHTML = `
      <style>
        :host {
          display: block;
        }
        .workflow-container {
          display: flex;
          flex-direction: column;
        }
        .progress-bar {
          height: 4px;
          background: var(--muted);
          border-radius: 2px;
          margin-bottom: var(--space-4);
          overflow: hidden;
        }
        .progress-bar__indicator {
          height: 100%;
          background: var(--success);
          width: 0%;
          transition: width 0.3s ease;
        }
        .steps-wrapper {
          display: flex;
          flex-direction: column;
        }
        .step {
          display: flex;
          gap: var(--space-3);
        }
        .step__indicator {
          display: flex;
          flex-direction: column;
          align-items: center;
        }
        .step__icon {
          width: 28px;
          height: 28px;
          border-radius: 50%;
          display: flex;
          align-items: center;
          justify-content: center;
          border: 2px solid var(--border);
          background: var(--card);
          transition: all 0.2s ease;
          flex-shrink: 0;
        }
        .step__icon svg {
          color: white;
        }
        .step--pending .step__icon {
          border-color: var(--muted-foreground);
        }
        .step--active .step__icon {
          border-color: var(--primary);
          background: var(--primary);
        }
        .step--completed .step__icon {
          border-color: var(--success);
          background: var(--success);
        }
        .step--error .step__icon {
          border-color: var(--destructive);
          background: var(--destructive);
        }
        .step--skipped .step__icon {
          border-color: var(--muted-foreground);
          background: var(--muted-foreground);
        }
        .step__line {
          width: 2px;
          flex-grow: 1;
          min-height: var(--space-4);
          background: var(--border);
          margin: var(--space-1) 0;
        }
        .step:last-child .step__line {
          display: none;
        }
        .step--completed .step__line,
        .step--skipped .step__line {
          background: var(--success);
        }
        .step__content {
          flex: 1;
          padding-bottom: var(--space-4);
          min-width: 0;
        }
        .step__header {
          display: flex;
          align-items: flex-start;
          justify-content: space-between;
          gap: var(--space-2);
        }
        .step__title {
          font-weight: var(--font-medium);
          color: var(--foreground);
          font-size: var(--text-sm);
        }
        .step--pending .step__title,
        .step--pending .step__description {
          color: var(--muted-foreground);
        }
        .step__optional {
          font-size: var(--text-xs);
          color: var(--muted-foreground);
          background: var(--muted);
          padding: 0 var(--space-1);
          border-radius: var(--radius-sm);
        }
        .step__description {
          font-size: var(--text-xs);
          color: var(--muted-foreground);
          margin-top: var(--space-1);
          line-height: 1.4;
        }
        .step__actions {
          margin-top: var(--space-3);
          display: flex;
          gap: var(--space-2);
        }
        .error-message {
          color: var(--destructive);
          font-size: var(--text-xs);
          margin-top: var(--space-2);
          padding: var(--space-2);
          background: oklch(from var(--destructive) l c h / 0.1);
          border-radius: var(--radius);
        }
      </style>
      <div class="workflow-container">
        <div class="progress-bar">
          <div class="progress-bar__indicator"></div>
        </div>
        <div class="steps-wrapper" id="steps-wrapper"></div>
      </div>
    `;
  }

  _render() {
    const wrapper = this.shadowRoot.getElementById('steps-wrapper');
    if (!wrapper || !this._steps || this._steps.length === 0) {
      return;
    }

    // Determine which step should be active
    this._determineActiveStep();

    // Render steps
    wrapper.innerHTML = this._steps.map(step => this._renderStep(step)).join('');

    // Update progress bar
    const progress = this._getProgress();
    const indicator = this.shadowRoot.querySelector('.progress-bar__indicator');
    if (indicator) {
      indicator.style.width = `${progress}%`;
    }

    // Add event listeners for action buttons
    wrapper.querySelectorAll('[data-action-event]').forEach(button => {
      button.addEventListener('click', () => {
        this.dispatchEvent(new CustomEvent(button.dataset.actionEvent, {
          bubbles: true,
          composed: true,
          detail: { stepId: button.dataset.stepId }
        }));
      });
    });

    // Add skip button listeners
    wrapper.querySelectorAll('[data-skip]').forEach(button => {
      button.addEventListener('click', () => {
        this.skipStep(button.dataset.skip);
      });
    });
  }

  _renderStep(step) {
    const isActionable = step.status === 'active' && step.action;
    const canSkip = step.status === 'active' && step.optional;

    return `
      <div class="step step--${step.status}" data-step-id="${step.id}">
        <div class="step__indicator">
          <div class="step__icon">${ICONS[step.status] || ''}</div>
          <div class="step__line"></div>
        </div>
        <div class="step__content">
          <div class="step__header">
            <div class="step__title">${this._escapeHtml(step.title)}</div>
            ${step.optional ? '<span class="step__optional">Optional</span>' : ''}
          </div>
          ${step.description ? `<div class="step__description">${this._escapeHtml(step.description)}</div>` : ''}
          ${step.status === 'error' && step.message ? `<div class="error-message">${this._escapeHtml(step.message)}</div>` : ''}
          ${isActionable || canSkip ? `
            <div class="step__actions">
              ${isActionable ? `
                <ds-button
                  variant="primary"
                  size="sm"
                  data-step-id="${step.id}"
                  data-action-event="${step.action.event}"
                >${step.action.label}</ds-button>
              ` : ''}
              ${canSkip ? `
                <ds-button
                  variant="ghost"
                  size="sm"
                  data-skip="${step.id}"
                >Skip</ds-button>
              ` : ''}
            </div>
          ` : ''}
        </div>
      </div>
    `;
  }

  _escapeHtml(text) {
    const div = document.createElement('div');
    div.textContent = text;
    return div.innerHTML;
  }
}

customElements.define('ds-workflow', DsWorkflow);
