<?php
/**
 * Treasury_Controller.php — خزانه پروژه
 * جریان نقدی | P&L | بودجه vs واقعی
 */

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

class Treasury_Controller {

    /* دسته‌بندی‌ها */
    const CATEGORIES = [
        'land'          => ['label'=>'خرید زمین',       'dir'=>'out', 'icon'=>'📍'],
        'construction'  => ['label'=>'ساخت و ساز',       'dir'=>'out', 'icon'=>'🏗️'],
        'permits'       => ['label'=>'مجوزها و عوارض',   'dir'=>'out', 'icon'=>'📋'],
        'design'        => ['label'=>'طراحی و مشاوره',   'dir'=>'out', 'icon'=>'✏️'],
        'marketing'     => ['label'=>'بازاریابی',        'dir'=>'out', 'icon'=>'📢'],
        'finance_cost'  => ['label'=>'هزینه مالی/بهره',  'dir'=>'out', 'icon'=>'💸'],
        'tax'           => ['label'=>'مالیات',           'dir'=>'out', 'icon'=>'🏛️'],
        'sales_income'  => ['label'=>'درآمد فروش واحد',  'dir'=>'in',  'icon'=>'💰'],
        'investor'      => ['label'=>'آورده سرمایه‌گذار','dir'=>'in',  'icon'=>'🤝'],
        'loan'          => ['label'=>'تسهیلات/وام',      'dir'=>'in',  'icon'=>'🏦'],
        'other'         => ['label'=>'سایر',             'dir'=>'both','icon'=>'📌'],
    ];

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

        // داشبورد یک پروژه
        register_rest_route($ns, '/treasury/project/(?P<project_id>\d+)/dashboard', [
            'methods'=>'GET', 'callback'=>[self::class,'get_project_dashboard'], 'permission_callback'=>$p,
        ]);

        // نمای کلی همه پروژه‌ها
        register_rest_route($ns, '/treasury/overview', [
            'methods'=>'GET', 'callback'=>[self::class,'get_overview'], 'permission_callback'=>$p,
        ]);

        // تراکنش‌ها
        register_rest_route($ns, '/treasury/entries', [
            ['methods'=>'GET',  'callback'=>[self::class,'get_entries'],   'permission_callback'=>$p],
            ['methods'=>'POST', 'callback'=>[self::class,'create_entry'],  'permission_callback'=>$p],
        ]);
        register_rest_route($ns, '/treasury/entries/(?P<id>\d+)', [
            ['methods'=>'PUT',    'callback'=>[self::class,'update_entry'], 'permission_callback'=>$p],
            ['methods'=>'DELETE', 'callback'=>[self::class,'delete_entry'], 'permission_callback'=>$p],
        ]);

        // بودجه
        register_rest_route($ns, '/treasury/budget/(?P<project_id>\d+)', [
            ['methods'=>'GET',  'callback'=>[self::class,'get_budget'],   'permission_callback'=>$p],
            ['methods'=>'POST', 'callback'=>[self::class,'save_budget'],  'permission_callback'=>$p],
        ]);

        // متادیتا (دسته‌بندی‌ها)
        register_rest_route($ns, '/treasury/categories', [
            'methods'=>'GET', 'callback'=>[self::class,'get_categories'], 'permission_callback'=>$p,
        ]);
    }

    /* ══════════════════════════════════════════════════════════
       داشبورد پروژه — قلب ماژول
    ══════════════════════════════════════════════════════════ */
    public static function get_project_dashboard( WP_REST_Request $req ): WP_REST_Response {
        global $wpdb;
        $pre = $wpdb->prefix;
        $pid = (int)$req->get_param('project_id');
        $deny = acl_deny_scope( acl_current_user_id(), 'project', $pid, 'treasury.view' );
        if ( $deny ) return $deny;

        // ── اطلاعات پروژه ───────────────────────────────────
        $project = $wpdb->get_row($wpdb->prepare(
            "SELECT p.*, l.name AS land_name
             FROM {$pre}pc_projects p
             LEFT JOIN {$pre}pc_lands l ON l.id = p.land_id
             WHERE p.id = %d", $pid
        ), ARRAY_A);

        if (!$project) return new WP_REST_Response(['message'=>'پروژه یافت نشد'], 404);

        // ── تراکنش‌های دستی ─────────────────────────────────
        $manual = $wpdb->get_results($wpdb->prepare(
            "SELECT direction, category, SUM(amount) AS total
             FROM {$pre}treasury_entries
             WHERE project_id=%d
             GROUP BY direction, category", $pid
        ), ARRAY_A);

        $manual_in  = array_filter($manual, fn($r)=>$r['direction']==='in');
        $manual_out = array_filter($manual, fn($r)=>$r['direction']==='out');

        // ── درآمد از فروش واحدها ────────────────────────────
        $sales_paid = (float)$wpdb->get_var($wpdb->prepare(
            "SELECT COALESCE(SUM(s.paid_amount),0)
             FROM {$pre}sales s
             JOIN {$pre}sale_units u ON u.id=s.unit_id
             WHERE u.project_id=%d AND s.status!='cancelled'", $pid
        ));
        $sales_total = (float)$wpdb->get_var($wpdb->prepare(
            "SELECT COALESCE(SUM(s.sale_price),0)
             FROM {$pre}sales s
             JOIN {$pre}sale_units u ON u.id=s.unit_id
             WHERE u.project_id=%d AND s.status!='cancelled'", $pid
        ));

        // ── هزینه از فاکتورهای خرید ─────────────────────────
        $invoice_cost = (float)$wpdb->get_var($wpdb->prepare(
            "SELECT COALESCE(SUM(total_amount),0)
             FROM {$pre}ai_purchase_invoices
             WHERE project_id=%d AND status!='cancelled'", $pid
        ));

        // ── هزینه از قراردادهای ساخت (پرداخت‌شده) ──────────
        $contract_paid = (float)$wpdb->get_var($wpdb->prepare(
            "SELECT COALESCE(SUM(py.paid_amount),0)
             FROM {$pre}contract_payments py
             JOIN {$pre}contracts c ON c.id=py.contract_id
             WHERE c.project_id=%d AND c.type='construction'
               AND py.status IN ('paid','partial')", $pid
        ));

        // ── خلاصه مالی ─────────────────────────────────────
        $manual_income  = array_sum(array_column(array_values($manual_in),  'total'));
        $manual_expense = array_sum(array_column(array_values($manual_out), 'total'));

        $total_income  = $sales_paid + $manual_income;
        $total_expense = $invoice_cost + $contract_paid + $manual_expense;
        $net_profit    = $total_income - $total_expense;
        $budget        = (float)($project['budget'] ?: 0);
        $budget_used   = $budget > 0 ? round($total_expense / $budget * 100, 1) : 0;

        // ── واحدهای پروژه ────────────────────────────────────
        $units = $wpdb->get_results($wpdb->prepare(
            "SELECT status, COUNT(*) AS cnt,
                    COALESCE(SUM(base_price),0) AS value
             FROM {$pre}sale_units
             WHERE project_id=%d
             GROUP BY status", $pid
        ), ARRAY_A);

        $unit_stats = [];
        foreach ($units as $u) $unit_stats[$u['status']] = $u;
        $total_units = array_sum(array_column($units, 'cnt'));
        $total_value = array_sum(array_column($units, 'value'));
        $sold_cnt    = ($unit_stats['sold']['cnt']??0) + ($unit_stats['transferred']['cnt']??0);
        $sold_value  = ($unit_stats['sold']['value']??0) + ($unit_stats['transferred']['value']??0);

        // ── هزینه بر اساس دسته‌بندی ─────────────────────────
        $expense_by_cat = [];
        // از تراکنش‌های دستی
        foreach ($manual_out as $row) {
            $k = $row['category'];
            $expense_by_cat[$k] = ($expense_by_cat[$k]??0) + (float)$row['total'];
        }
        // فاکتورهای خرید → construction
        if ($invoice_cost > 0) $expense_by_cat['construction'] = ($expense_by_cat['construction']??0) + $invoice_cost;
        // قراردادهای ساخت → construction
        if ($contract_paid > 0) $expense_by_cat['construction'] = ($expense_by_cat['construction']??0) + $contract_paid;

        // ── بودجه تفصیلی ─────────────────────────────────────
        $budget_rows = $wpdb->get_results($wpdb->prepare(
            "SELECT * FROM {$pre}treasury_budget WHERE project_id=%d", $pid
        ), ARRAY_A);
        $budget_by_cat = [];
        foreach ($budget_rows as $b) $budget_by_cat[$b['category']] = (float)$b['planned_amount'];

        // ── آخرین تراکنش‌ها ──────────────────────────────────
        $recent = $wpdb->get_results($wpdb->prepare(
            "SELECT * FROM {$pre}treasury_entries
             WHERE project_id=%d
             ORDER BY entry_date DESC, id DESC
             LIMIT 10", $pid
        ), ARRAY_A);

        // ── گزارش ماهانه (۶ ماه اخیر) ──────────────────────
        $monthly = $wpdb->get_results($wpdb->prepare(
            "SELECT DATE_FORMAT(entry_date,'%%Y-%%m') AS month,
                    direction, SUM(amount) AS total
             FROM {$pre}treasury_entries
             WHERE project_id=%d AND entry_date >= DATE_SUB(CURDATE(), INTERVAL 6 MONTH)
             GROUP BY month, direction
             ORDER BY month", $pid
        ), ARRAY_A);

        return new WP_REST_Response([
            'project'       => $project,
            'summary'       => [
                'total_income'    => $total_income,
                'total_expense'   => $total_expense,
                'net_profit'      => $net_profit,
                'net_pct'         => $total_income > 0 ? round($net_profit/$total_income*100,1) : 0,
                'budget'          => $budget,
                'budget_used_pct' => $budget_used,
                'sales_revenue'   => $sales_paid,
                'sales_forecast'  => $sales_total,
                'invoice_expense' => $invoice_cost,
                'contract_expense'=> $contract_paid,
            ],
            'units'         => [
                'total'       => $total_units,
                'sold'        => $sold_cnt,
                'available'   => ($unit_stats['available']['cnt']??0),
                'reserved'    => ($unit_stats['reserved']['cnt']??0),
                'total_value' => $total_value,
                'sold_value'  => $sold_value,
                'sell_pct'    => $total_units > 0 ? round($sold_cnt/$total_units*100,1) : 0,
            ],
            'expense_by_cat'=> $expense_by_cat,
            'budget_by_cat' => $budget_by_cat,
            'recent'        => $recent,
            'monthly'       => $monthly,
        ]);
    }

    /* ══════════════════════════════════════════════════════════
       نمای کلی همه پروژه‌ها
    ══════════════════════════════════════════════════════════ */
    public static function get_overview( WP_REST_Request $req ): WP_REST_Response {
        global $wpdb;
        $pre = $wpdb->prefix;

        $wheres = ["p.status != 'archived'"];
        $args   = [];
        $uid    = acl_current_user_id();
        if ( ! acl_append_scope_where( $uid, 'project', 'p.id', $wheres, $args ) ) {
            return new WP_REST_Response( [ 'data' => [] ] );
        }
        $where = 'WHERE ' . implode( ' AND ', $wheres );

        $sql = "SELECT p.id, p.name, p.status, p.budget, p.progress,
                    (SELECT COALESCE(SUM(amount),0) FROM {$pre}treasury_entries WHERE project_id=p.id AND direction='out') AS total_expense,
                    (SELECT COALESCE(SUM(amount),0) FROM {$pre}treasury_entries WHERE project_id=p.id AND direction='in')  AS total_income_manual,
                    (SELECT COALESCE(SUM(s.paid_amount),0) FROM {$pre}sales s JOIN {$pre}sale_units u ON u.id=s.unit_id WHERE u.project_id=p.id AND s.status!='cancelled') AS sales_income,
                    (SELECT COALESCE(SUM(total_amount),0) FROM {$pre}ai_purchase_invoices WHERE project_id=p.id AND status!='cancelled') AS invoice_expense,
                    (SELECT COUNT(*) FROM {$pre}sale_units WHERE project_id=p.id) AS unit_count,
                    (SELECT COUNT(*) FROM {$pre}sale_units WHERE project_id=p.id AND status IN ('sold','transferred')) AS sold_count
             FROM {$pre}pc_projects p
             {$where}
             ORDER BY p.id DESC";

        $projects = $args
            ? $wpdb->get_results( $wpdb->prepare( $sql, ...$args ), ARRAY_A )
            : $wpdb->get_results( $sql, ARRAY_A );

        foreach ($projects as &$pr) {
            $pr['total_income']  = (float)$pr['total_income_manual'] + (float)$pr['sales_income'];
            $pr['total_expense'] += (float)$pr['invoice_expense'];
            $pr['net_profit']    = $pr['total_income'] - $pr['total_expense'];
        }

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

    /* ══════════════════════════════════════════════════════════
       تراکنش‌ها
    ══════════════════════════════════════════════════════════ */
    public static function get_entries( WP_REST_Request $req ): WP_REST_Response {
        global $wpdb;
        $pre    = $wpdb->prefix;
        $wheres = ['1=1'];
        $args   = [];

        if ($v=$req->get_param('project_id')) { $wheres[]='e.project_id=%d'; $args[]=(int)$v; }
        $uid = acl_current_user_id();
        if ( ! acl_append_scope_where( $uid, 'project', 'e.project_id', $wheres, $args ) ) {
            return new WP_REST_Response( [ 'data' => [], 'total' => 0 ] );
        }
        if ($v=$req->get_param('direction'))  { $wheres[]='e.direction=%s';  $args[]=sanitize_text_field($v); }
        if ($v=$req->get_param('category'))   { $wheres[]='e.category=%s';   $args[]=sanitize_text_field($v); }
        if ($v=$req->get_param('from'))       { $wheres[]='e.entry_date>=%s'; $args[]=sanitize_text_field($v); }
        if ($v=$req->get_param('to'))         { $wheres[]='e.entry_date<=%s'; $args[]=sanitize_text_field($v); }

        $where = 'WHERE '.implode(' AND ',$wheres);
        $sql   = "SELECT e.*, p.name AS project_name
                  FROM {$pre}treasury_entries e
                  LEFT JOIN {$pre}pc_projects p ON p.id=e.project_id
                  {$where}
                  ORDER BY e.entry_date DESC, e.id DESC";

        $rows = $args
            ? $wpdb->get_results($wpdb->prepare($sql,...$args), ARRAY_A)
            : $wpdb->get_results($sql, ARRAY_A);

        // محاسبه موجودی جاری
        $balance = 0;
        $result  = array_reverse($rows??[]);
        foreach ($result as &$r) {
            $balance += $r['direction']==='in' ? (float)$r['amount'] : -(float)$r['amount'];
            $r['running_balance'] = $balance;
        }

        return new WP_REST_Response(['data'=>array_reverse($result), 'total'=>count($result)]);
    }

    public static function create_entry( WP_REST_Request $req ): WP_REST_Response {
        global $wpdb;
        $data = [
            'project_id'  => (int)$req->get_param('project_id'),
            'direction'   => sanitize_text_field($req->get_param('direction') ?: 'out'),
            'category'    => sanitize_text_field($req->get_param('category')  ?: 'other'),
            'amount'      => (float)($req->get_param('amount') ?: 0),
            'entry_date'  => sanitize_text_field($req->get_param('entry_date') ?: date('Y-m-d')),
            'description' => sanitize_text_field($req->get_param('description') ?: ''),
            'source'      => 'manual',
            'notes'       => sanitize_textarea_field($req->get_param('notes') ?: ''),
        ];
        if (!$data['project_id'])  return new WP_REST_Response(['message'=>'پروژه الزامی است'],400);
        $deny = acl_deny_scope( acl_current_user_id(), 'project', (int) $data['project_id'], 'treasury.view' );
        if ( $deny ) return $deny;
        if (!$data['amount'])      return new WP_REST_Response(['message'=>'مبلغ الزامی است'],400);
        if (!$data['description']) return new WP_REST_Response(['message'=>'شرح الزامی است'],400);
        foreach ($data as $k=>$v) { if ($v==='' || $v===null) unset($data[$k]); }
        $data['project_id']  = (int)$req->get_param('project_id');
        $data['amount']      = (float)$req->get_param('amount');
        $data['direction']   = sanitize_text_field($req->get_param('direction') ?: 'out');
        $data['entry_date']  = sanitize_text_field($req->get_param('entry_date') ?: date('Y-m-d'));
        $data['description'] = sanitize_text_field($req->get_param('description') ?: '');
        $data['category']    = sanitize_text_field($req->get_param('category') ?: 'other');
        $data['source']      = 'manual';

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

    public static function update_entry( WP_REST_Request $req ): WP_REST_Response {
        global $wpdb;
        $id   = (int)$req->get_param('id');
        $deny = acl_deny_entity_project( acl_current_user_id(), 'treasury_entries', $id, 'treasury.view' );
        if ( $deny ) return $deny;
        $data = [];
        foreach (['direction','category','entry_date','description','notes'] as $k) {
            $v=$req->get_param($k); if($v!==null) $data[$k]=sanitize_textarea_field((string)$v);
        }
        if ($req->get_param('amount')!==null) $data['amount']=(float)$req->get_param('amount');
        $wpdb->update($wpdb->prefix.'treasury_entries',$data,['id'=>$id]);
        return new WP_REST_Response(['success'=>true]);
    }

    public static function delete_entry( WP_REST_Request $req ): WP_REST_Response {
        global $wpdb;
        $id = (int)$req->get_param('id');
        $deny = acl_deny_entity_project( acl_current_user_id(), 'treasury_entries', $id, 'treasury.view' );
        if ( $deny ) return $deny;
        $source = $wpdb->get_var($wpdb->prepare("SELECT source FROM {$wpdb->prefix}treasury_entries WHERE id=%d",$id));
        if ($source!=='manual') return new WP_REST_Response(['message'=>'فقط تراکنش‌های دستی قابل حذف هستند'],409);
        $wpdb->delete($wpdb->prefix.'treasury_entries',['id'=>$id]);
        return new WP_REST_Response(['success'=>true]);
    }

    /* ── بودجه تفصیلی ─────────────────────────────────────── */
    public static function get_budget( WP_REST_Request $req ): WP_REST_Response {
        global $wpdb;
        $pid  = (int)$req->get_param('project_id');
        $deny = acl_deny_scope( acl_current_user_id(), 'project', $pid, 'treasury.view' );
        if ( $deny ) return $deny;
        $rows = $wpdb->get_results($wpdb->prepare(
            "SELECT * FROM {$wpdb->prefix}treasury_budget WHERE project_id=%d ORDER BY id",$pid
        ),ARRAY_A);
        return new WP_REST_Response(['data'=>$rows??[]]);
    }

    public static function save_budget( WP_REST_Request $req ): WP_REST_Response {
        global $wpdb;
        $pre  = $wpdb->prefix;
        $pid  = (int)$req->get_param('project_id');
        $deny = acl_deny_scope( acl_current_user_id(), 'project', $pid, 'treasury.view' );
        if ( $deny ) return $deny;
        $items = $req->get_param('items');
        if (!is_array($items)) return new WP_REST_Response(['message'=>'آیتم‌ها الزامی است'],400);
        foreach ($items as $item) {
            $cat    = sanitize_text_field($item['category']??'other');
            $label  = sanitize_text_field($item['label']??'');
            $amount = (float)($item['planned_amount']??0);
            $wpdb->query($wpdb->prepare(
                "INSERT INTO {$pre}treasury_budget (project_id,category,label,planned_amount)
                 VALUES (%d,%s,%s,%f)
                 ON DUPLICATE KEY UPDATE label=VALUES(label), planned_amount=VALUES(planned_amount)",
                $pid,$cat,$label,$amount
            ));
        }
        return new WP_REST_Response(['success'=>true]);
    }

    public static function get_categories(): WP_REST_Response {
        return new WP_REST_Response(['data'=>self::CATEGORIES]);
    }
}
