<?php
/**
 * Workflow_Controller — workflow پروژه
 *
 * Endpoints:
 *   GET    /acc/v1/wf/templates                       لیست قالب‌ها
 *   POST   /acc/v1/wf/templates                       افزودن قالب
 *   GET    /acc/v1/wf/templates/{id}                  جزئیات قالب
 *   PUT    /acc/v1/wf/templates/{id}                  ویرایش
 *   DELETE /acc/v1/wf/templates/{id}                  حذف
 *
 *   POST   /acc/v1/wf/instances                       اعمال قالب روی پروژه
 *   GET    /acc/v1/wf/instances/project/{pid}         instance یک پروژه
 *   GET    /acc/v1/wf/instances/{id}                  instance با مراحل و taskها
 *   DELETE /acc/v1/wf/instances/{id}                  حذف instance
 *
 *   PUT    /acc/v1/wf/stages/{id}                     ویرایش مرحله
 *   POST   /acc/v1/wf/stages/{id}/advance             حرکت به مرحله بعد
 *   POST   /acc/v1/wf/stages/{id}/start               شروع مرحله
 *
 *   PUT    /acc/v1/wf/tasks/{id}                      ویرایش task
 *   POST   /acc/v1/wf/tasks/{id}/complete             تکمیل task
 *
 *   GET    /acc/v1/wf/instances/{id}/transitions      تاریخچه
 */

if ( ! defined( 'ABSPATH' ) ) exit;

class Workflow_Controller {

    public static function register_routes(): void {
        $ns = 'acc/v1';
        $p  = 'acc_jwt_check_permission';

        register_rest_route($ns, '/wf/templates',           [['methods'=>'GET','callback'=>[self::class,'list_templates'],'permission_callback'=>$p],
                                                              ['methods'=>'POST','callback'=>[self::class,'create_template'],'permission_callback'=>$p]]);
        register_rest_route($ns, '/wf/templates/(?P<id>\d+)', [['methods'=>'GET','callback'=>[self::class,'get_template'],'permission_callback'=>$p],
                                                                ['methods'=>'PUT','callback'=>[self::class,'update_template'],'permission_callback'=>$p],
                                                                ['methods'=>'DELETE','callback'=>[self::class,'delete_template'],'permission_callback'=>$p]]);

        register_rest_route($ns, '/wf/instances',                    ['methods'=>'POST','callback'=>[self::class,'create_instance'],'permission_callback'=>$p]);
        register_rest_route($ns, '/wf/instances/project/(?P<pid>\d+)',['methods'=>'GET','callback'=>[self::class,'get_instance_by_project'],'permission_callback'=>$p]);
        register_rest_route($ns, '/wf/instances/(?P<id>\d+)',         [['methods'=>'GET','callback'=>[self::class,'get_instance'],'permission_callback'=>$p],
                                                                              ['methods'=>'DELETE','callback'=>[self::class,'delete_instance'],'permission_callback'=>$p]]);
        register_rest_route($ns, '/wf/instances/(?P<id>\d+)/transitions', ['methods'=>'GET','callback'=>[self::class,'get_transitions'],'permission_callback'=>$p]);

        register_rest_route($ns, '/wf/stages/(?P<id>\d+)',          ['methods'=>'PUT','callback'=>[self::class,'update_stage'],'permission_callback'=>$p]);
        register_rest_route($ns, '/wf/stages/(?P<id>\d+)/start',    ['methods'=>'POST','callback'=>[self::class,'start_stage'],'permission_callback'=>$p]);
        register_rest_route($ns, '/wf/stages/(?P<id>\d+)/advance',  ['methods'=>'POST','callback'=>[self::class,'advance_stage'],'permission_callback'=>$p]);

        register_rest_route($ns, '/wf/templates/(?P<id>\d+)/stages', ['methods'=>'POST','callback'=>[self::class,'create_template_stage'],'permission_callback'=>$p]);

        register_rest_route($ns, '/wf/tasks/(?P<id>\d+)',           ['methods'=>'PUT','callback'=>[self::class,'update_task'],'permission_callback'=>$p]);
        register_rest_route($ns, '/wf/tasks/(?P<id>\d+)/complete',  ['methods'=>'POST','callback'=>[self::class,'complete_task'],'permission_callback'=>$p]);
    }

    /* ════════════ قالب‌ها ════════════ */
    public static function list_templates( WP_REST_Request $req ): WP_REST_Response {
        global $wpdb;
        $rows = $wpdb->get_results(
            "SELECT t.*,
                    (SELECT COUNT(*) FROM {$wpdb->prefix}wf_template_stages WHERE template_id=t.id) AS stage_count,
                    (SELECT COUNT(*) FROM {$wpdb->prefix}wf_instances WHERE template_id=t.id)        AS instance_count
             FROM {$wpdb->prefix}wf_templates t
             WHERE t.is_active=1 ORDER BY t.id",
            ARRAY_A
        );
        return new WP_REST_Response(['data' => $rows ?? []]);
    }

    public static function get_template( WP_REST_Request $req ): WP_REST_Response {
        global $wpdb;
        $id = (int)$req->get_param('id');
        $tpl = $wpdb->get_row($wpdb->prepare(
            "SELECT * FROM {$wpdb->prefix}wf_templates WHERE id=%d", $id
        ), ARRAY_A);
        if (!$tpl) return new WP_REST_Response(['message'=>'یافت نشد'], 404);

        $tpl['stages'] = $wpdb->get_results($wpdb->prepare(
            "SELECT * FROM {$wpdb->prefix}wf_template_stages WHERE template_id=%d ORDER BY sort_order", $id
        ), ARRAY_A) ?? [];

        foreach ($tpl['stages'] as &$st) {
            $st['tasks'] = $wpdb->get_results($wpdb->prepare(
                "SELECT * FROM {$wpdb->prefix}wf_template_tasks WHERE stage_id=%d ORDER BY sort_order", $st['id']
            ), ARRAY_A) ?? [];
            $st['gates'] = $wpdb->get_results($wpdb->prepare(
                "SELECT * FROM {$wpdb->prefix}wf_template_gates WHERE stage_id=%d", $st['id']
            ), ARRAY_A) ?? [];
        }
        return new WP_REST_Response(['data'=>$tpl]);
    }

    public static function create_template( WP_REST_Request $req ): WP_REST_Response {
        global $wpdb;
        $wpdb->insert($wpdb->prefix.'wf_templates', [
            'code'        => sanitize_key($req->get_param('code') ?? ''),
            'name'        => sanitize_text_field($req->get_param('name') ?? ''),
            'description' => sanitize_textarea_field($req->get_param('description') ?? ''),
            'icon'        => sanitize_text_field($req->get_param('icon') ?? '📋'),
            'color'       => sanitize_text_field($req->get_param('color') ?? '#3b82f6'),
        ]);
        return new WP_REST_Response(['id'=>$wpdb->insert_id,'success'=>true], 201);
    }

    public static function update_template( WP_REST_Request $req ): WP_REST_Response {
        global $wpdb;
        $id = (int)$req->get_param('id');
        $data = [];
        foreach (['name','description','icon','color'] as $k) {
            if ($req->get_param($k) !== null) $data[$k] = sanitize_textarea_field((string)$req->get_param($k));
        }
        if ($data) $wpdb->update($wpdb->prefix.'wf_templates', $data, ['id'=>$id]);
        return new WP_REST_Response(['success'=>true]);
    }

    public static function delete_template( WP_REST_Request $req ): WP_REST_Response {
        global $wpdb;
        $id = (int)$req->get_param('id');
        $sys = $wpdb->get_var($wpdb->prepare("SELECT is_system FROM {$wpdb->prefix}wf_templates WHERE id=%d", $id));
        if ((int)$sys === 1) return new WP_REST_Response(['message'=>'قالب سیستمی قابل حذف نیست'], 409);
        $wpdb->update($wpdb->prefix.'wf_templates', ['is_active'=>0], ['id'=>$id]);
        return new WP_REST_Response(['success'=>true]);
    }

    /* ════════════ Instances ════════════ */
    public static function create_instance( WP_REST_Request $req ): WP_REST_Response {
        global $wpdb;
        $pre = $wpdb->prefix;

        $project_id  = (int)$req->get_param('project_id');
        $template_id = (int)$req->get_param('template_id');
        if (!$project_id || !$template_id) return new WP_REST_Response(['message'=>'project_id و template_id الزامی است'], 400);

        $deny = acl_deny_scope( acl_current_user_id(), 'project', $project_id, 'cpm.view' );
        if ( $deny ) return $deny;

        // اگر instance قبلی هست → خطا
        $exists = $wpdb->get_var($wpdb->prepare(
            "SELECT id FROM {$pre}wf_instances WHERE project_id=%d", $project_id
        ));
        if ($exists) return new WP_REST_Response(['message'=>'این پروژه workflow دارد', 'id'=>$exists], 409);

        // budget کل پروژه
        $project_budget = (float)$wpdb->get_var($wpdb->prepare(
            "SELECT COALESCE(budget,0) FROM {$pre}pc_projects WHERE id=%d", $project_id
        ));

        // ساخت instance
        $wpdb->insert("{$pre}wf_instances", [
            'project_id' => $project_id,
            'template_id' => $template_id,
            'status' => 'active',
        ]);
        $instance_id = (int)$wpdb->insert_id;

        // کپی stages
        $stages = $wpdb->get_results($wpdb->prepare(
            "SELECT * FROM {$pre}wf_template_stages WHERE template_id=%d ORDER BY sort_order", $template_id
        ), ARRAY_A);

        $first_stage_id = null;
        foreach ($stages as $idx => $st) {
            $wpdb->insert("{$pre}wf_instance_stages", [
                'instance_id'       => $instance_id,
                'template_stage_id' => $st['id'],
                'code'              => $st['code'],
                'name'              => $st['name'],
                'icon'              => $st['icon'],
                'color'             => $st['color'],
                'sort_order'        => $st['sort_order'],
                'status'            => $idx === 0 ? 'active' : 'pending',
                'budget_amount'     => $project_budget * ((float)$st['budget_pct'] / 100),
            ]);
            $instance_stage_id = (int)$wpdb->insert_id;
            if ($idx === 0) $first_stage_id = $instance_stage_id;

            // کپی tasks
            $tasks = $wpdb->get_results($wpdb->prepare(
                "SELECT * FROM {$pre}wf_template_tasks WHERE stage_id=%d ORDER BY sort_order", $st['id']
            ), ARRAY_A);
            foreach ($tasks as $t) {
                $wpdb->insert("{$pre}wf_instance_tasks", [
                    'instance_stage_id' => $instance_stage_id,
                    'title'             => $t['title'],
                    'description'       => $t['description'],
                    'sort_order'        => $t['sort_order'],
                    'is_required'       => $t['is_required'],
                ]);
            }
        }

        // به‌روزرسانی current_stage
        $wpdb->update("{$pre}wf_instances", ['current_stage_id' => $first_stage_id], ['id' => $instance_id]);

        // ثبت تاریخچه
        self::_log_transition($instance_id, null, $first_stage_id, 'create', 'Workflow ایجاد شد');

        return new WP_REST_Response(['id'=>$instance_id, 'success'=>true], 201);
    }

    public static function get_instance_by_project( WP_REST_Request $req ): WP_REST_Response {
        global $wpdb;
        $pid = (int)$req->get_param('pid');
        $deny = acl_deny_scope( acl_current_user_id(), 'project', $pid, 'cpm.view' );
        if ( $deny ) return $deny;
        $instance_id = $wpdb->get_var($wpdb->prepare(
            "SELECT id FROM {$wpdb->prefix}wf_instances WHERE project_id=%d", $pid
        ));
        if (!$instance_id) return new WP_REST_Response(['data'=>null]);
        return self::get_instance($req->set_param('id', $instance_id) ?? $req);
    }

    public static function get_instance( WP_REST_Request $req ): WP_REST_Response {
        global $wpdb;
        $pre = $wpdb->prefix;
        $id  = (int)$req->get_param('id');
        $deny = acl_deny_wf_instance( acl_current_user_id(), $id, 'cpm.view' );
        if ( $deny ) return $deny;

        $inst = $wpdb->get_row($wpdb->prepare(
            "SELECT i.*, t.name AS template_name, t.icon AS template_icon, p.name AS project_name
             FROM {$pre}wf_instances i
             LEFT JOIN {$pre}wf_templates t ON t.id = i.template_id
             LEFT JOIN {$pre}pc_projects  p ON p.id = i.project_id
             WHERE i.id=%d", $id
        ), ARRAY_A);
        if (!$inst) return new WP_REST_Response(['message'=>'یافت نشد'], 404);

        $inst['stages'] = $wpdb->get_results($wpdb->prepare(
            "SELECT * FROM {$pre}wf_instance_stages WHERE instance_id=%d ORDER BY sort_order", $id
        ), ARRAY_A) ?? [];

        foreach ($inst['stages'] as &$st) {
            $st['tasks'] = $wpdb->get_results($wpdb->prepare(
                "SELECT * FROM {$pre}wf_instance_tasks WHERE instance_stage_id=%d ORDER BY sort_order", $st['id']
            ), ARRAY_A) ?? [];
            $st['gates'] = $wpdb->get_results($wpdb->prepare(
                "SELECT * FROM {$pre}wf_template_gates WHERE stage_id=%d", $st['template_stage_id']
            ), ARRAY_A) ?? [];

            // محاسبه progress
            $total = count($st['tasks']);
            $done  = array_sum(array_map(fn($t) => $t['status'] === 'completed' ? 1 : 0, $st['tasks']));
            $st['progress_pct'] = $total > 0 ? round(($done / $total) * 100, 2) : 0;
            $st['tasks_total'] = $total;
            $st['tasks_done']  = $done;
        }

        // محاسبه progress کل
        $stage_count = count($inst['stages']);
        $progress = $stage_count ? array_sum(array_column($inst['stages'], 'progress_pct')) / $stage_count : 0;
        $inst['progress_pct'] = round($progress, 2);

        return new WP_REST_Response(['data'=>$inst]);
    }

    /* ════════════ Stages ════════════ */
    public static function update_stage( WP_REST_Request $req ): WP_REST_Response {
        $deny = acl_deny_wf_stage( acl_current_user_id(), (int) $req->get_param('id'), 'cpm.view' );
        if ( $deny ) return $deny;
        global $wpdb;
        $id = (int)$req->get_param('id');
        $data = [];
        foreach (['planned_start_date','planned_end_date','actual_start_date','actual_end_date','notes','status'] as $k) {
            if ($req->get_param($k) !== null) $data[$k] = sanitize_textarea_field((string)$req->get_param($k));
        }
        foreach (['budget_amount','spent_amount'] as $k) {
            if ($req->get_param($k) !== null) $data[$k] = (float)$req->get_param($k);
        }
        if ($data) $wpdb->update($wpdb->prefix.'wf_instance_stages', $data, ['id'=>$id]);
        return new WP_REST_Response(['success'=>true]);
    }

    public static function start_stage( WP_REST_Request $req ): WP_REST_Response {
        $deny = acl_deny_wf_stage( acl_current_user_id(), (int) $req->get_param('id'), 'cpm.view' );
        if ( $deny ) return $deny;
        global $wpdb;
        $id = (int)$req->get_param('id');
        $wpdb->update($wpdb->prefix.'wf_instance_stages', [
            'status' => 'active',
            'actual_start_date' => current_time('Y-m-d'),
        ], ['id'=>$id]);

        $stage = $wpdb->get_row($wpdb->prepare(
            "SELECT instance_id FROM {$wpdb->prefix}wf_instance_stages WHERE id=%d", $id
        ), ARRAY_A);
        if ($stage) {
            $wpdb->update($wpdb->prefix.'wf_instances', ['current_stage_id'=>$id], ['id'=>$stage['instance_id']]);
            self::_log_transition((int)$stage['instance_id'], null, $id, 'start_stage', 'مرحله شروع شد');
        }
        return new WP_REST_Response(['success'=>true]);
    }

    public static function advance_stage( WP_REST_Request $req ): WP_REST_Response {
        $deny = acl_deny_wf_stage( acl_current_user_id(), (int) $req->get_param('id'), 'cpm.view' );
        if ( $deny ) return $deny;
        global $wpdb;
        $pre = $wpdb->prefix;
        $id  = (int)$req->get_param('id');

        $stage = $wpdb->get_row($wpdb->prepare(
            "SELECT * FROM {$pre}wf_instance_stages WHERE id=%d", $id
        ), ARRAY_A);
        if (!$stage) return new WP_REST_Response(['message'=>'یافت نشد'], 404);

        // اعتبارسنجی: همه taskهای required باید complete باشند
        $pending = (int)$wpdb->get_var($wpdb->prepare(
            "SELECT COUNT(*) FROM {$pre}wf_instance_tasks
             WHERE instance_stage_id=%d AND is_required=1 AND status != 'completed'", $id
        ));
        $force = (bool)$req->get_param('force');
        if ($pending > 0 && !$force) {
            return new WP_REST_Response(['message'=>"{$pending} task اجباری ناتمام است. برای رد کردن از force=1 استفاده کنید", 'pending'=>$pending], 422);
        }

        // ست کردن مرحله جاری به completed
        $wpdb->update("{$pre}wf_instance_stages", [
            'status' => 'completed',
            'actual_end_date' => current_time('Y-m-d'),
            'progress_pct' => 100,
        ], ['id'=>$id]);

        // مرحله بعد
        $next = $wpdb->get_row($wpdb->prepare(
            "SELECT * FROM {$pre}wf_instance_stages
             WHERE instance_id=%d AND sort_order > %d
             ORDER BY sort_order ASC LIMIT 1",
            $stage['instance_id'], $stage['sort_order']
        ), ARRAY_A);

        if ($next) {
            $wpdb->update("{$pre}wf_instance_stages", [
                'status' => 'active',
                'actual_start_date' => current_time('Y-m-d'),
            ], ['id'=>$next['id']]);
            $wpdb->update("{$pre}wf_instances", ['current_stage_id'=>$next['id']], ['id'=>$stage['instance_id']]);
            self::_log_transition((int)$stage['instance_id'], $id, (int)$next['id'], 'advance', 'حرکت به مرحله بعد');
            return new WP_REST_Response(['success'=>true, 'next_stage'=>$next]);
        } else {
            // پایان پروژه
            $wpdb->update("{$pre}wf_instances", [
                'status' => 'completed',
                'completed_at' => current_time('mysql'),
                'progress_pct' => 100,
            ], ['id'=>$stage['instance_id']]);
            self::_log_transition((int)$stage['instance_id'], $id, null, 'complete', 'workflow کامل شد');
            return new WP_REST_Response(['success'=>true, 'completed'=>true]);
        }
    }

    /* ════════════ Tasks ════════════ */
    public static function update_task( WP_REST_Request $req ): WP_REST_Response {
        $deny = acl_deny_wf_task( acl_current_user_id(), (int) $req->get_param('id'), 'cpm.view' );
        if ( $deny ) return $deny;
        global $wpdb;
        $id = (int)$req->get_param('id');
        $data = [];
        foreach (['title','description','assigned_name','due_date','notes','status'] as $k) {
            if ($req->get_param($k) !== null) $data[$k] = sanitize_textarea_field((string)$req->get_param($k));
        }
        if ($req->get_param('assigned_to') !== null) $data['assigned_to'] = $req->get_param('assigned_to') ? (int)$req->get_param('assigned_to') : null;
        if ($data) $wpdb->update($wpdb->prefix.'wf_instance_tasks', $data, ['id'=>$id]);
        return new WP_REST_Response(['success'=>true]);
    }

    public static function complete_task( WP_REST_Request $req ): WP_REST_Response {
        $deny = acl_deny_wf_task( acl_current_user_id(), (int) $req->get_param('id'), 'cpm.view' );
        if ( $deny ) return $deny;
        global $wpdb;
        $id = (int)$req->get_param('id');
        $uid = (int) get_current_user_id();
        $uname = '';
        if ($uid) {
            $u = get_user_by('id', $uid);
            $uname = $u ? $u->display_name : '';
        }
        $wpdb->update($wpdb->prefix.'wf_instance_tasks', [
            'status' => 'completed',
            'completed_at' => current_time('mysql'),
            'completed_by' => $uid ?: null,
            'completed_by_name' => $uname,
        ], ['id'=>$id]);
        return new WP_REST_Response(['success'=>true]);
    }

    /* ════════════ تاریخچه ════════════ */
    public static function get_transitions( WP_REST_Request $req ): WP_REST_Response {
        $id = (int)$req->get_param('id');
        $deny = acl_deny_wf_instance( acl_current_user_id(), $id, 'cpm.view' );
        if ( $deny ) return $deny;
        global $wpdb;
        $rows = $wpdb->get_results($wpdb->prepare(
            "SELECT t.*,
                    fs.name AS from_stage_name,
                    ts.name AS to_stage_name
             FROM {$wpdb->prefix}wf_transitions t
             LEFT JOIN {$wpdb->prefix}wf_instance_stages fs ON fs.id = t.from_stage_id
             LEFT JOIN {$wpdb->prefix}wf_instance_stages ts ON ts.id = t.to_stage_id
             WHERE t.instance_id=%d
             ORDER BY t.created_at DESC LIMIT 200", $id
        ), ARRAY_A);
        return new WP_REST_Response(['data'=>$rows ?? []]);
    }

    public static function delete_instance( WP_REST_Request $req ): WP_REST_Response {
        global $wpdb;
        $pre = $wpdb->prefix;
        $id  = (int)$req->get_param('id');
        $deny = acl_deny_wf_instance( acl_current_user_id(), $id, 'cpm.view' );
        if ( $deny ) return $deny;
        $wpdb->delete("{$pre}wf_transitions",     ['instance_id' => $id]);
        $stages = $wpdb->get_col($wpdb->prepare("SELECT id FROM {$pre}wf_instance_stages WHERE instance_id=%d", $id));
        foreach ($stages as $sid) {
            $wpdb->delete("{$pre}wf_instance_tasks", ['instance_stage_id' => $sid]);
        }
        $wpdb->delete("{$pre}wf_instance_stages", ['instance_id' => $id]);
        $wpdb->delete("{$pre}wf_instances",       ['id' => $id]);
        return new WP_REST_Response(['success' => true]);
    }

    /* ════════════ Template Stages ════════════ */
    public static function create_template_stage( WP_REST_Request $req ): WP_REST_Response {
        global $wpdb;
        $pre = $wpdb->prefix;
        $template_id = (int)$req->get_param('id');

        if (!$wpdb->get_var($wpdb->prepare("SELECT id FROM {$pre}wf_templates WHERE id=%d", $template_id))) {
            return new WP_REST_Response(['message' => 'قالب یافت نشد'], 404);
        }

        $wpdb->insert("{$pre}wf_template_stages", [
            'template_id' => $template_id,
            'code'        => sanitize_key($req->get_param('code') ?? ''),
            'name'        => sanitize_text_field($req->get_param('name') ?? ''),
            'icon'        => sanitize_text_field($req->get_param('icon') ?? '▶'),
            'color'       => sanitize_text_field($req->get_param('color') ?? '#3b82f6'),
            'sort_order'  => (int)($req->get_param('sort_order') ?? 10),
            'budget_pct'  => (float)($req->get_param('budget_pct') ?? 0),
        ]);
        $stage_id = (int)$wpdb->insert_id;

        $tasks = $req->get_param('tasks');
        if (is_array($tasks)) {
            foreach ($tasks as $idx => $t) {
                $title = sanitize_text_field($t['title'] ?? '');
                if (!$title) continue;
                $wpdb->insert("{$pre}wf_template_tasks", [
                    'stage_id'    => $stage_id,
                    'title'       => $title,
                    'description' => sanitize_textarea_field($t['description'] ?? ''),
                    'sort_order'  => $idx,
                    'is_required' => empty($t['is_required']) ? 0 : 1,
                ]);
            }
        }

        return new WP_REST_Response(['id' => $stage_id, 'success' => true], 201);
    }

    private static function _log_transition( int $instance_id, ?int $from, ?int $to, string $action, string $notes ): void {
        global $wpdb;
        $uid = (int) get_current_user_id();
        $uname = '';
        if ($uid) {
            $u = get_user_by('id', $uid);
            $uname = $u ? $u->display_name : '';
        }
        $wpdb->insert($wpdb->prefix.'wf_transitions', [
            'instance_id' => $instance_id,
            'from_stage_id' => $from,
            'to_stage_id' => $to,
            'action' => $action,
            'notes' => $notes,
            'actor_id' => $uid ?: null,
            'actor_name' => $uname,
        ]);
    }
}
