<?php
/**
 * Assets_Controller — مدیریت اموال و تعمیر/نگهداری
 */

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

class Assets_Controller {

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

        register_rest_route($ns, '/assets/categories',           [['methods'=>'GET','callback'=>[self::class,'get_categories'],'permission_callback'=>$p],
                                                                  ['methods'=>'POST','callback'=>[self::class,'create_category'],'permission_callback'=>$p]]);
        register_rest_route($ns, '/assets/categories/(?P<id>\d+)', [['methods'=>'PUT','callback'=>[self::class,'update_category'],'permission_callback'=>$p],
                                                                    ['methods'=>'DELETE','callback'=>[self::class,'delete_category'],'permission_callback'=>$p]]);

        register_rest_route($ns, '/assets',           [['methods'=>'GET','callback'=>[self::class,'list_assets'],'permission_callback'=>$p],
                                                        ['methods'=>'POST','callback'=>[self::class,'create_asset'],'permission_callback'=>$p]]);
        register_rest_route($ns, '/assets/(?P<id>\d+)', [['methods'=>'GET','callback'=>[self::class,'get_asset'],'permission_callback'=>$p],
                                                          ['methods'=>'PUT','callback'=>[self::class,'update_asset'],'permission_callback'=>$p],
                                                          ['methods'=>'DELETE','callback'=>[self::class,'delete_asset'],'permission_callback'=>$p]]);

        /* PM schedules */
        register_rest_route($ns, '/assets/pm-schedules',           [['methods'=>'GET','callback'=>[self::class,'list_pm'],'permission_callback'=>$p],
                                                                     ['methods'=>'POST','callback'=>[self::class,'create_pm'],'permission_callback'=>$p]]);
        register_rest_route($ns, '/assets/pm-schedules/(?P<id>\d+)', [['methods'=>'PUT','callback'=>[self::class,'update_pm'],'permission_callback'=>$p],
                                                                       ['methods'=>'DELETE','callback'=>[self::class,'delete_pm'],'permission_callback'=>$p]]);
        register_rest_route($ns, '/assets/pm-schedules/due',         ['methods'=>'GET','callback'=>[self::class,'list_due_pm'],'permission_callback'=>$p]);

        /* Work Orders */
        register_rest_route($ns, '/assets/work-orders',           [['methods'=>'GET','callback'=>[self::class,'list_wo'],'permission_callback'=>$p],
                                                                    ['methods'=>'POST','callback'=>[self::class,'create_wo'],'permission_callback'=>$p]]);
        register_rest_route($ns, '/assets/work-orders/(?P<id>\d+)', [['methods'=>'GET','callback'=>[self::class,'get_wo'],'permission_callback'=>$p],
                                                                      ['methods'=>'PUT','callback'=>[self::class,'update_wo'],'permission_callback'=>$p]]);
        register_rest_route($ns, '/assets/work-orders/(?P<id>\d+)/complete', ['methods'=>'POST','callback'=>[self::class,'complete_wo'],'permission_callback'=>$p]);

        /* استهلاک */
        register_rest_route($ns, '/assets/depreciation/run',     ['methods'=>'POST','callback'=>[self::class,'run_depreciation'],'permission_callback'=>$p]);
        register_rest_route($ns, '/assets/(?P<id>\d+)/depreciation', ['methods'=>'GET','callback'=>[self::class,'get_asset_depreciation'],'permission_callback'=>$p]);

        register_rest_route($ns, '/assets/dashboard', ['methods'=>'GET','callback'=>[self::class,'dashboard'],'permission_callback'=>$p]);
    }

    /* ════════════ دسته‌بندی ════════════ */
    public static function get_categories( WP_REST_Request $req ): WP_REST_Response {
        global $wpdb;
        $rows = $wpdb->get_results(
            "SELECT c.*, (SELECT COUNT(*) FROM {$wpdb->prefix}assets WHERE category_id=c.id AND status != 'retired') AS asset_count
             FROM {$wpdb->prefix}asset_categories c
             WHERE c.is_active=1 ORDER BY c.parent_id, c.name",
            ARRAY_A
        );
        return new WP_REST_Response(['data'=>$rows ?? []]);
    }

    public static function create_category( WP_REST_Request $req ): WP_REST_Response {
        global $wpdb;
        $wpdb->insert($wpdb->prefix.'asset_categories', [
            'parent_id'    => (int)($req->get_param('parent_id') ?? 0),
            'code'         => sanitize_text_field($req->get_param('code') ?? ''),
            'name'         => sanitize_text_field($req->get_param('name') ?? ''),
            'icon'         => sanitize_text_field($req->get_param('icon') ?? '📦'),
            'depr_method'  => sanitize_text_field($req->get_param('depr_method') ?? 'straight_line'),
            'useful_years' => (int)($req->get_param('useful_years') ?? 5),
            'salvage_pct'  => (float)($req->get_param('salvage_pct') ?? 0),
        ]);
        return new WP_REST_Response(['id'=>$wpdb->insert_id,'success'=>true], 201);
    }

    public static function update_category( WP_REST_Request $req ): WP_REST_Response {
        global $wpdb;
        $id = (int)$req->get_param('id');
        $data = [];
        foreach (['code','name','icon','depr_method'] as $k) {
            if ($req->get_param($k) !== null) $data[$k] = sanitize_text_field((string)$req->get_param($k));
        }
        if ($req->get_param('useful_years') !== null) $data['useful_years'] = (int)$req->get_param('useful_years');
        if ($req->get_param('salvage_pct')  !== null) $data['salvage_pct']  = (float)$req->get_param('salvage_pct');
        if ($data) $wpdb->update($wpdb->prefix.'asset_categories', $data, ['id'=>$id]);
        return new WP_REST_Response(['success'=>true]);
    }

    public static function delete_category( WP_REST_Request $req ): WP_REST_Response {
        global $wpdb;
        $wpdb->update($wpdb->prefix.'asset_categories', ['is_active'=>0], ['id'=>(int)$req->get_param('id')]);
        return new WP_REST_Response(['success'=>true]);
    }

    /* ════════════ اموال ════════════ */
    public static function list_assets( WP_REST_Request $req ): WP_REST_Response {
        global $wpdb;
        $pre = $wpdb->prefix;
        $wheres = ['a.status != %s']; $args = ['deleted'];

        if ($v = $req->get_param('category_id')) { $wheres[] = 'a.category_id = %d'; $args[] = (int)$v; }
        if ($v = $req->get_param('status'))      { $wheres[] = 'a.status = %s';      $args[] = sanitize_text_field($v); }
        if ($v = $req->get_param('assigned_to')) { $wheres[] = 'a.assigned_to = %d'; $args[] = (int)$v; }
        if ($v = $req->get_param('search')) {
            $wheres[] = '(a.name LIKE %s OR a.asset_code LIKE %s OR a.serial_no LIKE %s)';
            $s = "%{$v}%"; $args[] = $s; $args[] = $s; $args[] = $s;
        }

        $where = 'WHERE ' . implode(' AND ', $wheres);
        $sql = "SELECT a.*, c.name AS category_name, c.icon AS category_icon
                FROM {$pre}assets a
                LEFT JOIN {$pre}asset_categories c ON c.id = a.category_id
                {$where}
                ORDER BY a.id DESC LIMIT 500";

        $rows = $wpdb->get_results($wpdb->prepare($sql, ...$args), ARRAY_A);
        return new WP_REST_Response(['data'=>$rows ?? []]);
    }

    public static function get_asset( WP_REST_Request $req ): WP_REST_Response {
        global $wpdb;
        $pre = $wpdb->prefix;
        $id  = (int)$req->get_param('id');

        $asset = $wpdb->get_row($wpdb->prepare(
            "SELECT a.*, c.name AS category_name, c.icon AS category_icon, c.useful_years, c.salvage_pct
             FROM {$pre}assets a
             LEFT JOIN {$pre}asset_categories c ON c.id = a.category_id
             WHERE a.id = %d", $id
        ), ARRAY_A);
        if (!$asset) return new WP_REST_Response(['message'=>'یافت نشد'], 404);

        $asset['documents'] = $wpdb->get_results($wpdb->prepare(
            "SELECT * FROM {$pre}asset_documents WHERE asset_id=%d ORDER BY uploaded_at DESC", $id
        ), ARRAY_A) ?? [];

        $asset['pm_schedules'] = $wpdb->get_results($wpdb->prepare(
            "SELECT * FROM {$pre}asset_pm_schedules WHERE asset_id=%d AND is_active=1 ORDER BY next_due_date", $id
        ), ARRAY_A) ?? [];

        $asset['work_orders'] = $wpdb->get_results($wpdb->prepare(
            "SELECT * FROM {$pre}asset_work_orders WHERE asset_id=%d ORDER BY reported_at DESC LIMIT 20", $id
        ), ARRAY_A) ?? [];

        $asset['depreciations'] = $wpdb->get_results($wpdb->prepare(
            "SELECT * FROM {$pre}asset_depreciations WHERE asset_id=%d ORDER BY period_year DESC, period_month DESC LIMIT 24", $id
        ), ARRAY_A) ?? [];

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

    public static function create_asset( WP_REST_Request $req ): WP_REST_Response {
        global $wpdb;
        $data = self::_asset_data($req);
        if (!$data['name']) return new WP_REST_Response(['message'=>'نام الزامی است'], 400);

        if (!$data['asset_code']) {
            $last = (int)$wpdb->get_var("SELECT COUNT(*) FROM {$wpdb->prefix}assets");
            $data['asset_code'] = 'AST-' . str_pad($last + 1, 5, '0', STR_PAD_LEFT);
        }
        if (!$data['current_value']) $data['current_value'] = $data['purchase_price'];

        $wpdb->insert($wpdb->prefix.'assets', $data);
        return new WP_REST_Response(['id'=>$wpdb->insert_id, 'asset_code'=>$data['asset_code'], 'success'=>true], 201);
    }

    public static function update_asset( WP_REST_Request $req ): WP_REST_Response {
        global $wpdb;
        $id = (int)$req->get_param('id');
        $data = self::_asset_data($req, true);
        if ($data) $wpdb->update($wpdb->prefix.'assets', $data, ['id'=>$id]);
        return new WP_REST_Response(['success'=>true]);
    }

    public static function delete_asset( WP_REST_Request $req ): WP_REST_Response {
        global $wpdb;
        $wpdb->update($wpdb->prefix.'assets', ['status'=>'retired'], ['id'=>(int)$req->get_param('id')]);
        return new WP_REST_Response(['success'=>true]);
    }

    private static function _asset_data( WP_REST_Request $req, bool $partial = false ): array {
        $fields = [
            'asset_code'=>'text','name'=>'text','category_id'=>'int_n',
            'serial_no'=>'text','plate_no'=>'text','brand'=>'text','model'=>'text','description'=>'textarea',
            'status'=>'text','condition_grade'=>'text',
            'purchase_date'=>'text','purchase_price'=>'float','current_value'=>'float',
            'supplier_id'=>'int_n','purchase_invoice_id'=>'int_n',
            'warranty_expiry'=>'text','insurance_expiry'=>'text','next_service_date'=>'text',
            'assigned_to'=>'int_n','assigned_name'=>'text',
            'location_id'=>'int_n','warehouse_id'=>'int_n','project_id'=>'int_n',
            'photo_url'=>'text','qr_code'=>'text','notes'=>'textarea',
        ];
        $data = [];
        foreach ($fields as $k => $type) {
            $v = $req->get_param($k);
            if ($partial && $v === null) continue;
            switch ($type) {
                case 'int_n':    $data[$k] = $v ? (int)$v : null; break;
                case 'float':    $data[$k] = (float)($v ?? 0); break;
                case 'textarea': $data[$k] = sanitize_textarea_field((string)$v); break;
                default:         $data[$k] = sanitize_text_field((string)$v);
            }
        }
        if (!$partial && empty($data['status'])) $data['status'] = 'active';
        return $data;
    }

    /* ════════════ PM Schedules ════════════ */
    public static function list_pm( WP_REST_Request $req ): WP_REST_Response {
        global $wpdb;
        $pre = $wpdb->prefix;
        $aid = (int)($req->get_param('asset_id') ?? 0);
        $where = $aid ? $wpdb->prepare("WHERE pm.asset_id=%d", $aid) : '';
        $rows = $wpdb->get_results(
            "SELECT pm.*, a.name AS asset_name, a.asset_code
             FROM {$pre}asset_pm_schedules pm
             LEFT JOIN {$pre}assets a ON a.id = pm.asset_id
             {$where} ORDER BY pm.next_due_date ASC", ARRAY_A
        );
        return new WP_REST_Response(['data'=>$rows ?? []]);
    }

    public static function list_due_pm( WP_REST_Request $req ): WP_REST_Response {
        global $wpdb;
        $pre = $wpdb->prefix;
        $days = (int)($req->get_param('days') ?? 30);
        $rows = $wpdb->get_results($wpdb->prepare(
            "SELECT pm.*, a.name AS asset_name, a.asset_code,
                    DATEDIFF(pm.next_due_date, CURDATE()) AS days_left
             FROM {$pre}asset_pm_schedules pm
             LEFT JOIN {$pre}assets a ON a.id = pm.asset_id
             WHERE pm.is_active=1 AND pm.next_due_date IS NOT NULL
               AND pm.next_due_date <= DATE_ADD(CURDATE(), INTERVAL %d DAY)
             ORDER BY pm.next_due_date ASC", $days
        ), ARRAY_A);
        return new WP_REST_Response(['data'=>$rows ?? []]);
    }

    public static function create_pm( WP_REST_Request $req ): WP_REST_Response {
        global $wpdb;
        $interval = (int)$req->get_param('interval_days');
        $last = sanitize_text_field($req->get_param('last_done_date') ?? '');
        $next = $last ? date('Y-m-d', strtotime($last . ' + ' . $interval . ' days'))
                      : date('Y-m-d', strtotime("+{$interval} days"));
        $wpdb->insert($wpdb->prefix.'asset_pm_schedules', [
            'asset_id'       => (int)$req->get_param('asset_id'),
            'title'          => sanitize_text_field($req->get_param('title') ?? ''),
            'description'    => sanitize_textarea_field($req->get_param('description') ?? ''),
            'interval_days'  => $interval,
            'last_done_date' => $last ?: null,
            'next_due_date'  => $next,
            'estimated_cost' => (float)($req->get_param('estimated_cost') ?? 0),
            'priority'       => sanitize_text_field($req->get_param('priority') ?? 'medium'),
        ]);
        return new WP_REST_Response(['id'=>$wpdb->insert_id, 'success'=>true], 201);
    }

    public static function update_pm( WP_REST_Request $req ): WP_REST_Response {
        global $wpdb;
        $id = (int)$req->get_param('id');
        $data = [];
        foreach (['title','description','priority','last_done_date','next_due_date'] as $k) {
            if ($req->get_param($k) !== null) $data[$k] = sanitize_textarea_field((string)$req->get_param($k));
        }
        if ($req->get_param('interval_days')  !== null) $data['interval_days']  = (int)$req->get_param('interval_days');
        if ($req->get_param('estimated_cost') !== null) $data['estimated_cost'] = (float)$req->get_param('estimated_cost');
        if ($req->get_param('is_active')      !== null) $data['is_active']      = (int)$req->get_param('is_active');
        if ($data) $wpdb->update($wpdb->prefix.'asset_pm_schedules', $data, ['id'=>$id]);
        return new WP_REST_Response(['success'=>true]);
    }

    public static function delete_pm( WP_REST_Request $req ): WP_REST_Response {
        global $wpdb;
        $wpdb->update($wpdb->prefix.'asset_pm_schedules', ['is_active'=>0], ['id'=>(int)$req->get_param('id')]);
        return new WP_REST_Response(['success'=>true]);
    }

    /* ════════════ Work Orders ════════════ */
    public static function list_wo( WP_REST_Request $req ): WP_REST_Response {
        global $wpdb;
        $pre = $wpdb->prefix;
        $wheres = []; $args = [];

        if ($v = $req->get_param('asset_id')) { $wheres[] = 'wo.asset_id = %d'; $args[] = (int)$v; }
        if ($v = $req->get_param('status'))   { $wheres[] = 'wo.status = %s';   $args[] = sanitize_text_field($v); }
        if ($v = $req->get_param('type'))     { $wheres[] = 'wo.type = %s';     $args[] = sanitize_text_field($v); }
        if ($v = $req->get_param('assigned_to')){ $wheres[] = 'wo.assigned_to = %d'; $args[] = (int)$v; }

        $where = $wheres ? 'WHERE ' . implode(' AND ', $wheres) : '';
        $sql = "SELECT wo.*, a.name AS asset_name, a.asset_code
                FROM {$pre}asset_work_orders wo
                LEFT JOIN {$pre}assets a ON a.id = wo.asset_id
                {$where}
                ORDER BY wo.reported_at DESC LIMIT 500";
        $rows = $args ? $wpdb->get_results($wpdb->prepare($sql, ...$args), ARRAY_A)
                      : $wpdb->get_results($sql, ARRAY_A);
        return new WP_REST_Response(['data'=>$rows ?? []]);
    }

    public static function get_wo( WP_REST_Request $req ): WP_REST_Response {
        global $wpdb;
        $pre = $wpdb->prefix;
        $id  = (int)$req->get_param('id');

        $wo = $wpdb->get_row($wpdb->prepare(
            "SELECT wo.*, a.name AS asset_name, a.asset_code, a.category_id
             FROM {$pre}asset_work_orders wo
             LEFT JOIN {$pre}assets a ON a.id = wo.asset_id
             WHERE wo.id=%d", $id
        ), ARRAY_A);
        if (!$wo) return new WP_REST_Response(['message'=>'یافت نشد'], 404);

        $wo['items'] = $wpdb->get_results($wpdb->prepare(
            "SELECT i.*, p.name AS product_name, p.unit
             FROM {$pre}asset_wo_items i
             LEFT JOIN {$pre}inv_products p ON p.id = i.product_id
             WHERE i.wo_id=%d", $id
        ), ARRAY_A) ?? [];

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

    public static function create_wo( WP_REST_Request $req ): WP_REST_Response {
        global $wpdb;
        $pre = $wpdb->prefix;

        $year = date('Y');
        $last = (int)$wpdb->get_var($wpdb->prepare(
            "SELECT COUNT(*) FROM {$pre}asset_work_orders WHERE wo_no LIKE %s", "WO-{$year}-%"
        ));
        $wo_no = sprintf('WO-%s-%04d', $year, $last + 1);

        $uid = (int)get_current_user_id();
        $uname = '';
        if ($uid) { $u = get_user_by('id', $uid); $uname = $u ? $u->display_name : ''; }

        $wpdb->insert("{$pre}asset_work_orders", [
            'wo_no'           => $wo_no,
            'asset_id'        => (int)$req->get_param('asset_id'),
            'type'            => sanitize_text_field($req->get_param('type') ?? 'corrective'),
            'priority'        => sanitize_text_field($req->get_param('priority') ?? 'medium'),
            'status'          => 'open',
            'title'           => sanitize_text_field($req->get_param('title') ?? ''),
            'problem_desc'    => sanitize_textarea_field($req->get_param('problem_desc') ?? ''),
            'reporter_id'     => $uid ?: null,
            'reporter_name'   => $uname,
            'assigned_to'     => $req->get_param('assigned_to') ? (int)$req->get_param('assigned_to') : null,
            'assigned_name'   => sanitize_text_field($req->get_param('assigned_name') ?? ''),
            'external_vendor' => sanitize_text_field($req->get_param('external_vendor') ?? ''),
            'pm_schedule_id'  => $req->get_param('pm_schedule_id') ? (int)$req->get_param('pm_schedule_id') : null,
            'due_date'        => sanitize_text_field($req->get_param('due_date') ?? '') ?: null,
        ]);
        $wid = (int)$wpdb->insert_id;

        // به‌روزرسانی وضعیت دارایی
        $aid = (int)$req->get_param('asset_id');
        $wpdb->update("{$pre}assets", ['status'=>'in_repair'], ['id'=>$aid]);

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

    public static function update_wo( WP_REST_Request $req ): WP_REST_Response {
        global $wpdb;
        $id = (int)$req->get_param('id');
        $data = [];
        foreach (['title','problem_desc','solution_desc','status','priority','assigned_name','external_vendor','due_date','notes'] as $k) {
            if ($req->get_param($k) !== null) $data[$k] = sanitize_textarea_field((string)$req->get_param($k));
        }
        foreach (['labor_cost','parts_cost','total_cost','downtime_hours'] as $k) {
            if ($req->get_param($k) !== null) $data[$k] = (float)$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 (isset($data['status']) && $data['status'] === 'in_progress' && !$req->get_param('started_at')) {
            $data['started_at'] = current_time('mysql');
        }

        if ($data) $wpdb->update($wpdb->prefix.'asset_work_orders', $data, ['id'=>$id]);

        // ردیف‌ها
        $items = $req->get_param('items');
        if (is_array($items)) {
            $wpdb->delete($wpdb->prefix.'asset_wo_items', ['wo_id'=>$id]);
            foreach ($items as $it) {
                $qty   = (float)($it['qty'] ?? 0);
                $price = (float)($it['unit_cost'] ?? 0);
                $wpdb->insert($wpdb->prefix.'asset_wo_items', [
                    'wo_id'       => $id,
                    'item_type'   => sanitize_text_field($it['item_type'] ?? 'part'),
                    'product_id'  => !empty($it['product_id']) ? (int)$it['product_id'] : null,
                    'description' => sanitize_text_field($it['description'] ?? ''),
                    'qty'         => $qty,
                    'unit_cost'   => $price,
                    'total_cost'  => $qty * $price,
                ]);
            }
        }
        return new WP_REST_Response(['success'=>true]);
    }

    public static function complete_wo( WP_REST_Request $req ): WP_REST_Response {
        global $wpdb;
        $pre = $wpdb->prefix;
        $id  = (int)$req->get_param('id');

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

        // محاسبه total
        $items_total = (float)$wpdb->get_var($wpdb->prepare(
            "SELECT COALESCE(SUM(total_cost),0) FROM {$pre}asset_wo_items WHERE wo_id=%d", $id
        ));

        $solution = sanitize_textarea_field($req->get_param('solution_desc') ?? '');
        $labor    = (float)($req->get_param('labor_cost') ?? $wo['labor_cost']);

        $wpdb->update("{$pre}asset_work_orders", [
            'status'        => 'closed',
            'completed_at'  => current_time('mysql'),
            'solution_desc' => $solution,
            'labor_cost'    => $labor,
            'parts_cost'    => $items_total,
            'total_cost'    => $labor + $items_total,
        ], ['id'=>$id]);

        // به‌روزرسانی دارایی
        $wpdb->update("{$pre}assets", [
            'status' => 'active',
            'condition_grade' => sanitize_text_field($req->get_param('condition_grade') ?? 'good'),
        ], ['id'=>$wo['asset_id']]);

        // اگر از PM schedule بود → به‌روزرسانی schedule
        if ($wo['pm_schedule_id']) {
            $pm = $wpdb->get_row($wpdb->prepare("SELECT * FROM {$pre}asset_pm_schedules WHERE id=%d", $wo['pm_schedule_id']), ARRAY_A);
            if ($pm) {
                $today = date('Y-m-d');
                $next  = date('Y-m-d', strtotime($today . ' + ' . $pm['interval_days'] . ' days'));
                $wpdb->update("{$pre}asset_pm_schedules", [
                    'last_done_date' => $today,
                    'next_due_date'  => $next,
                ], ['id'=>$wo['pm_schedule_id']]);
            }
        }

        return new WP_REST_Response(['success'=>true, 'total_cost' => $labor + $items_total]);
    }

    /* ════════════ استهلاک ════════════ */
    public static function run_depreciation( WP_REST_Request $req ): WP_REST_Response {
        global $wpdb;
        $pre = $wpdb->prefix;
        $year  = (int)($req->get_param('year') ?? date('Y'));
        $month = (int)($req->get_param('month') ?? date('n'));

        $assets = $wpdb->get_results(
            "SELECT a.id, a.purchase_price, a.current_value, a.purchase_date,
                    c.useful_years, c.salvage_pct
             FROM {$pre}assets a
             LEFT JOIN {$pre}asset_categories c ON c.id = a.category_id
             WHERE a.status='active' AND a.purchase_price > 0",
            ARRAY_A
        );

        $processed = 0;
        foreach ($assets as $a) {
            $useful_years = (int)($a['useful_years'] ?? 5);
            $salvage_pct  = (float)($a['salvage_pct'] ?? 0);
            $salvage = $a['purchase_price'] * ($salvage_pct / 100);
            $depreciable = $a['purchase_price'] - $salvage;
            $monthly_depr = $depreciable / ($useful_years * 12);

            // جلوگیری از دوبار محاسبه
            $exists = $wpdb->get_var($wpdb->prepare(
                "SELECT id FROM {$pre}asset_depreciations
                 WHERE asset_id=%d AND period_year=%d AND period_month=%d",
                $a['id'], $year, $month
            ));
            if ($exists) continue;

            $book_before = (float)$a['current_value'];
            $book_after  = max($salvage, $book_before - $monthly_depr);
            $actual_depr = $book_before - $book_after;

            $wpdb->insert("{$pre}asset_depreciations", [
                'asset_id' => (int)$a['id'],
                'period_year' => $year,
                'period_month' => $month,
                'depr_amount' => $actual_depr,
                'book_value_before' => $book_before,
                'book_value_after'  => $book_after,
            ]);

            $wpdb->update("{$pre}assets", ['current_value' => $book_after], ['id'=>$a['id']]);
            $processed++;
        }

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

    public static function get_asset_depreciation( WP_REST_Request $req ): WP_REST_Response {
        global $wpdb;
        $id = (int)$req->get_param('id');
        $rows = $wpdb->get_results($wpdb->prepare(
            "SELECT * FROM {$wpdb->prefix}asset_depreciations WHERE asset_id=%d ORDER BY period_year DESC, period_month DESC", $id
        ), ARRAY_A);
        return new WP_REST_Response(['data'=>$rows ?? []]);
    }

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

        $total_assets = (int)$wpdb->get_var("SELECT COUNT(*) FROM {$pre}assets WHERE status != 'retired'");
        $active_value = (float)$wpdb->get_var("SELECT COALESCE(SUM(current_value),0) FROM {$pre}assets WHERE status='active'");
        $in_repair    = (int)$wpdb->get_var("SELECT COUNT(*) FROM {$pre}assets WHERE status='in_repair'");

        $by_category = $wpdb->get_results(
            "SELECT c.name, c.icon, COUNT(a.id) AS cnt, COALESCE(SUM(a.current_value),0) AS value
             FROM {$pre}asset_categories c
             LEFT JOIN {$pre}assets a ON a.category_id=c.id AND a.status != 'retired'
             GROUP BY c.id ORDER BY cnt DESC",
            ARRAY_A
        );

        $open_wo = (int)$wpdb->get_var("SELECT COUNT(*) FROM {$pre}asset_work_orders WHERE status IN ('open','in_progress')");
        $due_pm  = (int)$wpdb->get_var("SELECT COUNT(*) FROM {$pre}asset_pm_schedules WHERE is_active=1 AND next_due_date <= DATE_ADD(CURDATE(), INTERVAL 30 DAY)");

        $maintenance_cost_ytd = (float)$wpdb->get_var(
            "SELECT COALESCE(SUM(total_cost),0) FROM {$pre}asset_work_orders
             WHERE status='closed' AND YEAR(completed_at) = YEAR(CURDATE())"
        );

        return new WP_REST_Response([
            'total_assets'         => $total_assets,
            'active_value'         => $active_value,
            'in_repair_count'      => $in_repair,
            'open_wo_count'        => $open_wo,
            'due_pm_count'         => $due_pm,
            'maintenance_cost_ytd' => $maintenance_cost_ytd,
            'by_category'          => $by_category ?? [],
        ]);
    }
}
