/**
 * Workflow Catalog
 *
 * Single source of truth for every workflow type known to the frontend:
 * what it's called, what category/description/icons it has, how many steps
 * it has and what they're called, what its initial payload looks like, and
 * which Vue component renders it.
 *
 * Each workflow has a fully co-located component + metadata as a static
 * `meta` option on the component (`Component.meta`, right next to
 * `name`/`props`/etc.) in `@/components/workflow/workflows/*.vue` - this
 * file simply imports those components and reads `.meta` off of them to
 * build the catalog below.
 *
 * This replaces the previous design of a parallel `BaseWorkflow` class
 * hierarchy (metadata) plus a separate per-step `ComponentRegistry.js`
 * (components) - both concerns now live in one flat array with each
 * component responsible for its own metadata and UI implementation.
 */
import FotoFirstBulkImportWorkflow from '@/components/workflow/workflows/FotoFirstBulkImportWorkflow.vue';
import BulkItemImportWorkflow from '@/components/workflow/workflows/BulkItemImportWorkflow.vue';
import InventoryAuditWorkflow from '@/components/workflow/workflows/InventoryAuditWorkflow.vue';
import StorageOptimizationWorkflow from '@/components/workflow/workflows/StorageOptimizationWorkflow.vue';
import MaintenanceScheduleWorkflow from '@/components/workflow/workflows/MaintenanceScheduleWorkflow.vue';
import ExpiryCheckWorkflow from '@/components/workflow/workflows/ExpiryCheckWorkflow.vue';
import BackupRestoreWorkflow from '@/components/workflow/workflows/BackupRestoreWorkflow.vue';

/**
 * Workflows with a fully co-located component + metadata.
 */
const workflows = [
    {...FotoFirstBulkImportWorkflow.meta, component: FotoFirstBulkImportWorkflow},
    {...BulkItemImportWorkflow.meta, component: BulkItemImportWorkflow},
    {...InventoryAuditWorkflow.meta, component: InventoryAuditWorkflow},
    {...StorageOptimizationWorkflow.meta, component: StorageOptimizationWorkflow},
    {...MaintenanceScheduleWorkflow.meta, component: MaintenanceScheduleWorkflow},
    {...ExpiryCheckWorkflow.meta, component: ExpiryCheckWorkflow},
    {...BackupRestoreWorkflow.meta, component: BackupRestoreWorkflow},
];

/**
 * Get every workflow in the catalog.
 * @returns {Array<Object>}
 */
export function getAllWorkflows() {
    return workflows;
}

/**
 * Get a single workflow definition by id.
 * @param {string} id
 * @returns {Object|undefined}
 */
export function getWorkflow(slug) {
    return workflows.find(workflow => workflow.slug === slug);
}

/**
 * Get the Vue component implementing a workflow's UI, if any.
 * @param {string} id
 * @returns {Object|null}
 */
export function getWorkflowComponent(id) {
    return getWorkflow(id)?.component || null;
}

/**
 * Get all workflows belonging to a category.
 * @param {string} category
 * @returns {Array<Object>}
 */
export function getWorkflowsByCategory(category) {
    return workflows.filter(workflow => workflow.category === category);
}

/**
 * Get all unique categories present in the catalog.
 * @returns {Array<string>}
 */
export function getWorkflowCategories() {
    return [...new Set(workflows.map(workflow => workflow.category))];
}

/**
 * Build the payload sent to the backend to start a new instance of a
 * workflow, merging the common `workflow_config` metadata block with the
 * workflow's own initial payload fields.
 * @param {Object} workflow - A workflow definition, e.g. from getWorkflow()
 * @returns {Object}
 */
export function buildWorkflowApiPayload(workflow) {
    const ownPayload = workflow.getInitialPayload ? workflow.getInitialPayload() : {};
    return {
        title: workflow.title,
        slug: workflow.slug,
        state: 'running',
        current_step: 1,
        total_steps: workflow.stepDefinitions.length,
        payload: {
            ...ownPayload
        }
    };
}

/**
 * The backend stores WorkflowInstance.payload as an opaque string - it never
 * parses or understands it as JSON. The frontend is fully responsible for
 * serializing it before sending and deserializing it after receiving.
 */
export function serializeWorkflowPayload(workflow) {
    console.log(workflow);
    if (!workflow || !('payload' in workflow)) return workflow;
    return {...workflow, payload: JSON.stringify(workflow.payload ?? {})};
}

export function deserializeWorkflowPayload(workflow) {
    if (!workflow) return workflow;
    let payload = {};
    try {
        payload = workflow.payload ? JSON.parse(workflow.payload) : {};
    } catch (e) {
        console.error('Failed to parse workflow payload JSON:', e);
    }
    return {...workflow, payload};
}

export default {
    getAllWorkflows,
    getWorkflow,
    getWorkflowComponent,
    getWorkflowsByCategory,
    getWorkflowCategories,
    buildWorkflowApiPayload,
    serializeWorkflowPayload,
    deserializeWorkflowPayload
};
