<?php
declare(strict_types=1);

require_once __DIR__ . '/../config/database.php';
require_once __DIR__ . '/../app/helpers/rbac.php';
require_once __DIR__ . '/../app/helpers/auth.php';
require_once __DIR__ . '/../app/helpers/notification.php';
require_once __DIR__ . '/../app/helpers/audit.php';
require_once __DIR__ . '/../app/helpers/api_security.php';
require_once __DIR__ . '/../app/helpers/soft_delete.php';
require_once __DIR__ . '/../app/helpers/workflow.php';

requireApiLogin();
enforceCsrfForUnsafeRequest();

$action = $_GET['action'] ?? '';

try {
    switch ($action) {

        case 'list_templates':
            if (!isAdmin() && !can('workflow.templates.view')) respond(['status' => 'error', 'message' => 'Unauthorized']);
            $stmt = $pdo->query("SELECT wt.*, (SELECT COUNT(*) FROM workflow_template_steps WHERE template_id = wt.id) AS step_count FROM workflow_templates wt ORDER BY wt.name");
            respond(['status' => 'success', 'data' => $stmt->fetchAll()]);
            break;

        case 'get_template':
            if (!isAdmin() && !can('workflow.templates.view')) respond(['status' => 'error', 'message' => 'Unauthorized']);
            $id = (int)($_GET['id'] ?? 0);
            if ($id <= 0) respond(['status' => 'error', 'message' => 'Invalid ID']);
            $stmt = $pdo->prepare("SELECT * FROM workflow_templates WHERE id = ?");
            $stmt->execute([$id]);
            $tmpl = $stmt->fetch();
            if (!$tmpl) respond(['status' => 'error', 'message' => 'Template not found']);
            $stmt = $pdo->prepare("SELECT * FROM workflow_template_steps WHERE template_id = ? ORDER BY step_order");
            $stmt->execute([$id]);
            $tmpl['steps'] = $stmt->fetchAll();
            respond(['status' => 'success', 'data' => $tmpl]);
            break;

        case 'save_template':
            if (!isAdmin() && !can('workflow.templates.manage')) respond(['status' => 'error', 'message' => 'Unauthorized']);
            $id = (int)($_POST['id'] ?? 0);
            $name = trim($_POST['name'] ?? '');
            $module = trim($_POST['module'] ?? '');
            $description = trim($_POST['description'] ?? '');
            $is_active = (int)($_POST['is_active'] ?? 1);
            if (!$name || !$module) respond(['status' => 'error', 'message' => 'Name and module are required']);
            $steps = json_decode($_POST['steps'] ?? '[]', true);
            if (!is_array($steps) || empty($steps)) respond(['status' => 'error', 'message' => 'At least one step is required']);
            $pdo->beginTransaction();
            try {
                if ($id > 0) {
                    $pdo->prepare("UPDATE workflow_templates SET name = ?, module = ?, description = ?, is_active = ? WHERE id = ?")->execute([$name, $module, $description, $is_active, $id]);
                    $pdo->prepare("DELETE FROM workflow_template_steps WHERE template_id = ?")->execute([$id]);
                } else {
                    $pdo->prepare("INSERT INTO workflow_templates (name, module, description, is_active) VALUES (?, ?, ?, ?)")->execute([$name, $module, $description, $is_active]);
                    $id = (int)$pdo->lastInsertId();
                }
                $order = 1;
                $ins = $pdo->prepare("INSERT INTO workflow_template_steps (template_id, step_order, label, role_id, can_delegate) VALUES (?, ?, ?, ?, ?)");
                foreach ($steps as $step) {
                    $label = trim($step['label'] ?? '');
                    $roleId = (int)($step['role_id'] ?? 0);
                    $canDelegate = (int)($step['can_delegate'] ?? 1);
                    if (!$label || $roleId <= 0) continue;
                    $ins->execute([$id, $order++, $label, $roleId, $canDelegate]);
                }
                $pdo->commit();
                doAudit($pdo, $id > 0 ? 'update' : 'create', "Workflow template '{$name}' saved", $id);
                respond(['status' => 'success', 'message' => 'Template saved', 'id' => $id]);
            } catch (Exception $e) {
                $pdo->rollBack();
                respond(['status' => 'error', 'message' => $e->getMessage()]);
            }
            break;

        case 'delete_template':
            if (!isAdmin() && !can('workflow.templates.manage')) respond(['status' => 'error', 'message' => 'Unauthorized']);
            $id = (int)($_POST['id'] ?? 0);
            if ($id <= 0) respond(['status' => 'error', 'message' => 'Invalid ID']);
            $pdo->prepare("DELETE FROM workflow_templates WHERE id = ?")->execute([$id]);
            doAudit($pdo, 'delete', "Workflow template #{$id} deleted", $id);
            respond(['status' => 'success', 'message' => 'Template deleted']);
            break;

        case 'start':
            if (!can('workflow.start')) respond(['status' => 'error', 'message' => 'Unauthorized']);
            $module = trim($_POST['module'] ?? '');
            $recordId = (int)($_POST['record_id'] ?? 0);
            $templateId = (int)($_POST['template_id'] ?? 0);
            $userId = (int)($_SESSION['user_id'] ?? 0);
            if (!$module || $recordId <= 0) respond(['status' => 'error', 'message' => 'Module and record_id are required']);
            $runId = workflowStart($pdo, $module, $recordId, $templateId > 0 ? $templateId : null, $userId);
            doAudit($pdo, 'start', "Workflow started for {$module} #{$recordId}", $runId);
            respond(['status' => 'success', 'message' => 'Workflow started', 'run_id' => $runId]);
            break;

        case 'approve':
            if (!can('workflow.approve')) respond(['status' => 'error', 'message' => 'Unauthorized']);
            $stepId = (int)($_POST['step_id'] ?? 0);
            $comment = trim($_POST['comment'] ?? '');
            $userId = (int)($_SESSION['user_id'] ?? 0);
            if ($stepId <= 0) respond(['status' => 'error', 'message' => 'Invalid step']);
            $result = workflowApprove($pdo, $stepId, $userId, $comment);
            doAudit($pdo, 'approve', "Step #{$stepId} approved", $stepId);
            respond(['status' => 'success', 'message' => $result['status'] === 'workflow_completed' ? 'Workflow fully approved' : 'Step approved', 'data' => $result]);
            break;

        case 'reject':
            if (!can('workflow.approve')) respond(['status' => 'error', 'message' => 'Unauthorized']);
            $stepId = (int)($_POST['step_id'] ?? 0);
            $comment = trim($_POST['comment'] ?? '');
            $userId = (int)($_SESSION['user_id'] ?? 0);
            if ($stepId <= 0) respond(['status' => 'error', 'message' => 'Invalid step']);
            if (!$comment) respond(['status' => 'error', 'message' => 'Comment is required']);
            workflowReject($pdo, $stepId, $userId, $comment);
            doAudit($pdo, 'reject', "Workflow rejected at step #{$stepId}", $stepId);
            respond(['status' => 'success', 'message' => 'Workflow rejected']);
            break;

        case 'return':
            if (!can('workflow.approve')) respond(['status' => 'error', 'message' => 'Unauthorized']);
            $stepId = (int)($_POST['step_id'] ?? 0);
            $comment = trim($_POST['comment'] ?? '');
            $userId = (int)($_SESSION['user_id'] ?? 0);
            if ($stepId <= 0) respond(['status' => 'error', 'message' => 'Invalid step']);
            if (!$comment) respond(['status' => 'error', 'message' => 'Comment is required']);
            workflowReturn($pdo, $stepId, $userId, $comment);
            doAudit($pdo, 'return', "Workflow returned at step #{$stepId}", $stepId);
            respond(['status' => 'success', 'message' => 'Workflow returned for correction']);
            break;

        case 'list_modules':
            if (!isAdmin()) respond(['status' => 'error', 'message' => 'Unauthorized']);
            respond(['status' => 'success', 'data' => $pdo->query("SELECT * FROM workflow_modules ORDER BY display_name")->fetchAll()]);
            break;

        case 'save_module':
            if (!isAdmin()) respond(['status' => 'error', 'message' => 'Unauthorized']);
            $id = (int)($_POST['id'] ?? 0);
            $module = trim($_POST['module'] ?? '');
            $displayName = trim($_POST['display_name'] ?? '');
            $tableName = trim($_POST['table_name'] ?? '');
            $creatorColumn = trim($_POST['creator_column'] ?: 'created_by');
            $statusColumn = trim($_POST['status_column'] ?: 'status');
            $approvedValue = trim($_POST['approved_value'] ?: 'approved');
            $rejectedValue = trim($_POST['rejected_value'] ?: 'rejected');
            $returnedValue = trim($_POST['returned_value'] ?: 'returned');
            $isActive = (int)($_POST['is_active'] ?? 1);
            if (!$module || !$displayName || !$tableName) respond(['status' => 'error', 'message' => 'Module, display name, and table name are required']);
            if ($id > 0) {
                $stmt = $pdo->prepare("UPDATE workflow_modules SET module=?, display_name=?, table_name=?, creator_column=?, status_column=?, approved_value=?, rejected_value=?, returned_value=?, is_active=? WHERE id=?");
                $stmt->execute([$module, $displayName, $tableName, $creatorColumn, $statusColumn, $approvedValue, $rejectedValue, $returnedValue, $isActive, $id]);
            } else {
                $stmt = $pdo->prepare("INSERT INTO workflow_modules (module, display_name, table_name, creator_column, status_column, approved_value, rejected_value, returned_value, is_active) VALUES (?,?,?,?,?,?,?,?,?)");
                $stmt->execute([$module, $displayName, $tableName, $creatorColumn, $statusColumn, $approvedValue, $rejectedValue, $returnedValue, $isActive]);
            }
            doAudit($pdo, $id > 0 ? 'update' : 'create', "Workflow module '{$displayName}' saved");
            respond(['status' => 'success', 'message' => 'Module saved']);
            break;

        case 'delete_module':
            if (!isAdmin()) respond(['status' => 'error', 'message' => 'Unauthorized']);
            $id = (int)($_POST['id'] ?? 0);
            if ($id <= 0) respond(['status' => 'error', 'message' => 'Invalid ID']);
            $pdo->prepare("DELETE FROM workflow_modules WHERE id = ?")->execute([$id]);
            doAudit($pdo, 'delete', "Workflow module #{$id} deleted");
            respond(['status' => 'success', 'message' => 'Module deleted']);
            break;

        case 'my_pending':
            $userId = (int)($_SESSION['user_id'] ?? 0);
            $status = $_GET['status'] ?? 'pending';
            $valid = ['pending', 'approved', 'rejected', 'returned'];
            if (!in_array($status, $valid, true)) $status = 'pending';
            $stmt = $pdo->prepare("
                SELECT rs.*, r.module, r.record_id, r.template_id, wt.name AS template_name,
                    u1.name AS assigned_user_name, u2.name AS delegate_user_name
                FROM workflow_run_steps rs
                JOIN workflow_runs r ON r.id = rs.run_id
                JOIN workflow_templates wt ON wt.id = r.template_id
                LEFT JOIN users u1 ON u1.id = rs.assigned_user_id
                LEFT JOIN users u2 ON u2.id = rs.delegate_user_id
                WHERE rs.status = ?
                AND (rs.assigned_user_id = ? OR rs.delegate_user_id = ? OR rs.role_id IN (SELECT role_id FROM users WHERE id = ?))
                ORDER BY rs.created_at DESC
            ");
            $stmt->execute([$status, $userId, $userId, $userId]);
            respond(['status' => 'success', 'data' => $stmt->fetchAll()]);
            break;

        case 'status':
            $module = trim($_GET['module'] ?? '');
            $recordId = (int)($_GET['record_id'] ?? 0);
            if (!$module || $recordId <= 0) respond(['status' => 'error', 'message' => 'Module and record_id are required']);
            $run = $pdo->prepare("SELECT * FROM workflow_runs WHERE module = ? AND record_id = ? ORDER BY id DESC LIMIT 1");
            $run->execute([$module, $recordId]);
            $run = $run->fetch();
            if (!$run) respond(['status' => 'success', 'data' => null]);
            $steps = $pdo->prepare("SELECT rs.*, u1.name AS assigned_user_name, u2.name AS delegate_user_name, u3.name AS action_by_name FROM workflow_run_steps rs LEFT JOIN users u1 ON u1.id = rs.assigned_user_id LEFT JOIN users u2 ON u2.id = rs.delegate_user_id LEFT JOIN users u3 ON u3.id = rs.action_by WHERE rs.run_id = ? ORDER BY rs.step_order");
            $steps->execute([$run['id']]);
            $run['steps'] = $steps->fetchAll();
            respond(['status' => 'success', 'data' => $run]);
            break;

        case 'resubmit':
            if (!can('workflow.resubmit')) respond(['status' => 'error', 'message' => 'Unauthorized']);
            $module = trim($_POST['module'] ?? '');
            $recordId = (int)($_POST['record_id'] ?? 0);
            $userId = (int)($_SESSION['user_id'] ?? 0);
            if (!$module || $recordId <= 0) respond(['status' => 'error', 'message' => 'Module and record_id are required']);
            $run = $pdo->prepare("SELECT * FROM workflow_runs WHERE module = ? AND record_id = ? AND status = 'returned' ORDER BY id DESC LIMIT 1");
            $run->execute([$module, $recordId]);
            $run = $run->fetch();
            if (!$run) respond(['status' => 'error', 'message' => 'No returned workflow found']);
            $pdo->beginTransaction();
            try {
                $pdo->prepare("UPDATE workflow_runs SET status = 'pending', current_step_order = ? WHERE id = ?")->execute([$run['current_step_order'], $run['id']]);
                $pdo->prepare("UPDATE workflow_run_steps SET status = 'pending', action_by = NULL, comment = NULL, acted_at = NULL WHERE run_id = ? AND step_order >= ?")->execute([$run['id'], $run['current_step_order']]);
                $pdo->commit();
                doAudit($pdo, 'resubmit', "Workflow resubmitted for {$module} #{$recordId}", $run['id']);
                respond(['status' => 'success', 'message' => 'Workflow resubmitted']);
            } catch (Exception $e) {
                $pdo->rollBack();
                respond(['status' => 'error', 'message' => $e->getMessage()]);
            }
            break;

        default:
            respond(['status' => 'error', 'message' => 'Invalid action']);
    }
} catch (Throwable $e) {
    respond(['status' => 'error', 'message' => $e->getMessage()]);
}

function respond(array $data): void { apiRespond($data); }

function doAudit(PDO $pdo, string $action, string $description, ?int $recordId = null): void
{
    audit($pdo, (int)($_SESSION['user_id'] ?? 0), $action, 'workflow', $recordId ?? 0, $description, null, null);
}
