import { Pool } from 'pg';
import { config } from '../config';
import { ReportNodeStatusInput, ReportWorkflowStatusInput } from '../dsl/types';

const pool = new Pool({ connectionString: config.database.url });

/**
 * Report a node's execution status to the database.
 */
export async function reportNodeStatus(input: ReportNodeStatusInput): Promise<void> {
  const { instanceId, nodeId, nodeType, nodeLabel, status, input: nodeInput, output, error } = input;

  if (status === 'RUNNING') {
    // Create or update node execution record with RUNNING status
    await pool.query(
      `INSERT INTO t_workflow_node_execution (instance_id, node_id, node_type, node_label, status, input, started_at, created_at, updated_at)
       VALUES ($1, $2, $3, $4, $5, $6, NOW(), NOW(), NOW())
       ON CONFLICT (instance_id, node_id) DO UPDATE SET
         status = $5, input = $6, started_at = NOW(), updated_at = NOW()`,
      [instanceId, nodeId, nodeType, nodeLabel || null, status, nodeInput ? JSON.stringify(nodeInput) : null],
    );
  } else {
    // Update with final status
    await pool.query(
      `UPDATE t_workflow_node_execution
       SET status = $1, output = $2, error = $3, finished_at = NOW(), updated_at = NOW()
       WHERE instance_id = $4 AND node_id = $5`,
      [status, output ? JSON.stringify(output) : null, error ? JSON.stringify(error) : null, instanceId, nodeId],
    );
  }
}

/**
 * Create a workflow instance for a cron-triggered run.
 * Used by cronTriggerWorkflow before delegating to dslWorkflow.
 */
export async function createCronInstance(input: {
  workflowId: number;
  versionId: number;
  scheduleId: string;
}): Promise<{ instanceId: number }> {
  const { rows } = await pool.query(
    `INSERT INTO t_workflow_instance
       (workflow_id, version_id, status, context, creator, created_at, updated_at)
     VALUES ($1, $2, 'PENDING', $3, 'cron', NOW(), NOW())
     RETURNING id`,
    [
      input.workflowId,
      input.versionId,
      JSON.stringify({ scheduleId: input.scheduleId, scheduledAt: new Date().toISOString() }),
    ],
  );
  return { instanceId: Number(rows[0].id) };
}

/**
 * Report overall workflow execution status.
 */
export async function reportWorkflowStatus(input: ReportWorkflowStatusInput): Promise<void> {
  const { instanceId, status, result } = input;

  const updates: string[] = ['status = $1', 'updated_at = NOW()'];
  const values: any[] = [status];
  let paramIdx = 2;

  if (status === 'RUNNING') {
    updates.push(`started_at = NOW()`);
  }

  if (status === 'COMPLETED' || status === 'FAILED' || status === 'CANCELLED') {
    updates.push(`finished_at = NOW()`);
  }

  if (result !== undefined) {
    updates.push(`result = $${paramIdx}`);
    values.push(JSON.stringify(result));
    paramIdx++;
  }

  values.push(instanceId);
  await pool.query(
    `UPDATE t_workflow_instance SET ${updates.join(', ')} WHERE id = $${paramIdx}`,
    values,
  );
}
