<?php
if (!defined('ABSPATH')) exit;

/**
 * ACC_Purchase_Controller
 * REST API for Purchases: Suppliers, Invoices
 */
class ACC_Purchase_Controller {

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

        // ── ACL-aware permission callbacks ────────────────────
        $pView = function_exists('acl_permission_callback') ? acl_permission_callback('purchase.view')              : $p;
        $pSup  = function_exists('acl_permission_callback') ? acl_permission_callback('purchase.suppliers.manage')  : $p;
        $pCre  = function_exists('acl_permission_callback') ? acl_permission_callback('purchase.invoices.create')   : $p;
        $pEdit = function_exists('acl_permission_callback') ? acl_permission_callback('purchase.invoices.edit')     : $p;
        $pFin  = function_exists('acl_permission_callback') ? acl_permission_callback('purchase.invoices.finalize') : $p;

        // ── Suppliers ──────────────────────────────────────────────────────
        register_rest_route($ns, '/purchase/suppliers', [
            ['methods' => 'GET',  'callback' => [self::class,'get_suppliers'],   'permission_callback' => $pView],
            ['methods' => 'POST', 'callback' => [self::class,'create_supplier'], 'permission_callback' => $pSup],
        ]);
        register_rest_route($ns, '/purchase/suppliers/(?P<id>\d+)', [
            ['methods' => 'PUT',    'callback' => [self::class,'update_supplier'], 'permission_callback' => $pSup],
            ['methods' => 'DELETE', 'callback' => [self::class,'delete_supplier'], 'permission_callback' => $pSup],
        ]);

        // ── Purchase Invoices ─────────────────────────────────────────────
        register_rest_route($ns, '/purchase/invoices', [
            ['methods' => 'GET',  'callback' => [self::class,'get_invoices'],   'permission_callback' => $pView],
            ['methods' => 'POST', 'callback' => [self::class,'create_invoice'], 'permission_callback' => $pCre],
        ]);
        register_rest_route($ns, '/purchase/invoices/(?P<id>\d+)', [
            ['methods' => 'GET',    'callback' => [self::class,'get_invoice'],   'permission_callback' => $pView],
            ['methods' => 'PUT',    'callback' => [self::class,'update_invoice'], 'permission_callback' => $pEdit],
            ['methods' => 'DELETE', 'callback' => [self::class,'delete_invoice'], 'permission_callback' => $pEdit],
        ]);
        register_rest_route($ns, '/purchase/invoices/(?P<id>\d+)/finalize', [
            'methods' => 'POST', 'callback' => [self::class,'finalize_invoice'], 'permission_callback' => $pFin,
        ]);
        register_rest_route($ns, '/purchase/invoices/(?P<id>\d+)/cancel', [
            'methods' => 'POST', 'callback' => [self::class,'cancel_invoice'], 'permission_callback' => $pEdit,
        ]);

        // ── Reports ────────────────────────────────────────────────────────
        register_rest_route($ns, '/purchase/reports/summary', [
            'methods' => 'GET', 'callback' => [self::class,'report_summary'], 'permission_callback' => 'acc_jwt_check_permission',
        ]);
    }

    // =========================================================
    // SUPPLIERS
    // =========================================================

    public static function get_suppliers(WP_REST_Request $req): array {
        global $wpdb;
        $search = sanitize_text_field($req->get_param('search') ?? '');
        $where  = $search
            ? $wpdb->prepare('WHERE is_active=1 AND (name LIKE %s OR code LIKE %s)', "%{$search}%", "%{$search}%")
            : 'WHERE is_active = 1';
        $rows = $wpdb->get_results(
            "SELECT * FROM {$wpdb->prefix}ai_purchase_suppliers {$where} ORDER BY name ASC",
            ARRAY_A
        );
        return ['success' => true, 'data' => $rows ?: []];
    }

    public static function create_supplier(WP_REST_Request $req): WP_REST_Response {
        global $wpdb;
        $wpdb->insert($wpdb->prefix . 'ai_purchase_suppliers', [
            'code'           => sanitize_text_field($req->get_param('code')           ?? ''),
            'name'           => sanitize_text_field($req->get_param('name')),
            'phone'          => sanitize_text_field($req->get_param('phone')          ?? ''),
            'email'          => sanitize_email($req->get_param('email')               ?? ''),
            'address'        => sanitize_textarea_field($req->get_param('address')    ?? ''),
            'tax_id'         => sanitize_text_field($req->get_param('tax_id')         ?? ''),
            'contact_person' => sanitize_text_field($req->get_param('contact_person') ?? ''),
            'bank_iban'      => sanitize_text_field($req->get_param('bank_iban')      ?? ''),
            'bank_name'      => sanitize_text_field($req->get_param('bank_name')      ?? ''),
            'is_active'      => 1,
        ]);
        return new WP_REST_Response(['success' => true, 'id' => $wpdb->insert_id], 201);
    }

    public static function update_supplier(WP_REST_Request $req): WP_REST_Response {
        global $wpdb;
        $id = (int) $req->get_param('id');
        $data = [];
        foreach (['code','name','phone','email','tax_id','contact_person','bank_iban','bank_name'] as $f) {
            if ($req->has_param($f)) $data[$f] = sanitize_text_field($req->get_param($f));
        }
        if ($req->has_param('address')) $data['address'] = sanitize_textarea_field($req->get_param('address'));
        if ($req->has_param('is_active')) $data['is_active'] = (int) $req->get_param('is_active');
        if (!empty($data)) $wpdb->update($wpdb->prefix . 'ai_purchase_suppliers', $data, ['id' => $id]);
        return new WP_REST_Response(['success' => true], 200);
    }

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

    // =========================================================
    // INVOICES
    // =========================================================

    public static function get_invoices(WP_REST_Request $req): array {
        global $wpdb;
        $page   = max(1, (int) ($req->get_param('page')     ?? 1));
        $size   = max(1, min(100, (int) ($req->get_param('per_page') ?? 20)));
        $offset = ($page - 1) * $size;
        $status     = sanitize_key($req->get_param('status') ?? '');
        $project_id = $req->get_param('project_id') ? (int)$req->get_param('project_id') : null;
        $conds = [];
        $args  = [];
        if ($status)     { $conds[] = 'i.status=%s';     $args[] = $status; }
        if ($project_id) { $conds[] = 'i.project_id=%d'; $args[] = $project_id; }

        $uid = acl_current_user_id();
        $wh  = acl_scope_sql_filter($uid, 'warehouse', 'i.warehouse_id');
        if ($wh) {
            $conds[] = trim($wh['sql'], ' AND ');
            $args    = array_merge($args, $wh['args']);
        }
        $pj = acl_scope_sql_filter($uid, 'project', 'i.project_id');
        if ($pj) {
            $conds[] = trim($pj['sql'], ' AND ');
            $args    = array_merge($args, $pj['args']);
        }

        $where     = $conds ? 'WHERE ' . implode(' AND ', $conds) : '';
        $count_sql = "SELECT COUNT(*) FROM {$wpdb->prefix}ai_purchase_invoices i {$where}";
        $list_sql  = "SELECT i.*, s.name AS supplier_name, p.name AS project_name
             FROM {$wpdb->prefix}ai_purchase_invoices i
             LEFT JOIN {$wpdb->prefix}ai_purchase_suppliers s ON s.id = i.supplier_id
             LEFT JOIN {$wpdb->prefix}pc_projects p ON p.id = i.project_id
             {$where} ORDER BY i.id DESC LIMIT %d OFFSET %d";

        if ($args) {
            $total = (int) $wpdb->get_var($wpdb->prepare($count_sql, ...$args));
            $rows  = $wpdb->get_results($wpdb->prepare($list_sql, ...array_merge($args, [$size, $offset])), ARRAY_A);
        } else {
            $total = (int) $wpdb->get_var($count_sql);
            $rows  = $wpdb->get_results($wpdb->prepare($list_sql, $size, $offset), ARRAY_A);
        }

        return ['success' => true, 'data' => $rows ?: [], 'total' => $total];
    }

    public static function get_invoice(WP_REST_Request $req): WP_REST_Response {
        global $wpdb;
        $id = (int) $req->get_param('id');
        $invoice = $wpdb->get_row($wpdb->prepare(
            "SELECT i.*, s.name AS supplier_name
             FROM {$wpdb->prefix}ai_purchase_invoices i
             LEFT JOIN {$wpdb->prefix}ai_purchase_suppliers s ON s.id = i.supplier_id
             WHERE i.id=%d", $id
        ), ARRAY_A);
        if (!$invoice) return new WP_REST_Response(['success' => false, 'message' => 'یافت نشد'], 404);

        $uid  = acl_current_user_id();
        $deny = acl_deny_scope( $uid, 'warehouse', $invoice['warehouse_id'] ? (int)$invoice['warehouse_id'] : null, 'purchase.view' );
        if ( $deny ) return $deny;
        $deny = acl_deny_scope( $uid, 'project', $invoice['project_id'] ? (int)$invoice['project_id'] : null, 'purchase.view' );
        if ( $deny ) return $deny;

        $items = $wpdb->get_results($wpdb->prepare(
            "SELECT ii.*, p.name AS product_name, p.unit
             FROM {$wpdb->prefix}ai_purchase_invoice_items ii
             LEFT JOIN {$wpdb->prefix}ai_sale_products p ON p.id = ii.product_id
             WHERE ii.invoice_id=%d ORDER BY ii.sort_order ASC", $id
        ), ARRAY_A);

        $invoice['items'] = $items ?: [];
        return new WP_REST_Response(['success' => true, 'data' => $invoice], 200);
    }

    public static function create_invoice(WP_REST_Request $req): WP_REST_Response {
        global $wpdb;
        $year   = date('Y');
        $seq    = (int) $wpdb->get_var("SELECT COUNT(*) FROM {$wpdb->prefix}ai_purchase_invoices WHERE invoice_no LIKE 'PURCH-{$year}-%'");
        $inv_no = sprintf('PURCH-%s-%04d', $year, $seq + 1);
        $items  = $req->get_param('items') ?? [];
        $totals = self::_calculate_totals($items);

        $uid = acl_current_user_id();
        $wh  = $req->get_param('warehouse_id') ? (int) $req->get_param('warehouse_id') : null;
        $pj  = $req->get_param('project_id')  ? (int) $req->get_param('project_id')  : null;
        $deny = acl_deny_scope( $uid, 'warehouse', $wh, 'purchase.invoices.create' );
        if ( $deny ) return $deny;
        $deny = acl_deny_scope( $uid, 'project', $pj, 'purchase.invoices.create' );
        if ( $deny ) return $deny;

        $wpdb->insert($wpdb->prefix . 'ai_purchase_invoices', [
            'invoice_no'      => $req->get_param('invoice_no') ?: $inv_no,
            'supplier_id'     => $req->get_param('supplier_id') ? (int) $req->get_param('supplier_id') : null,
            'project_id'      => $req->get_param('project_id')  ? (int) $req->get_param('project_id')  : null,
            'warehouse_id'    => $req->get_param('warehouse_id') ? (int) $req->get_param('warehouse_id') : null,
            'ref_number'      => sanitize_text_field($req->get_param('ref_number')    ?? ''),
            'payment_terms'   => (int) ($req->get_param('payment_terms') ?? 0),
            'invoice_date'    => sanitize_text_field($req->get_param('invoice_date') ?: date('Y-m-d')),
            'due_date'        => $req->get_param('due_date') ? sanitize_text_field($req->get_param('due_date')) : null,
            'status'          => 'draft',
            'subtotal'        => $totals['subtotal'],
            'discount_amount' => $totals['discount_amount'],
            'net_amount'      => $totals['net_amount'],
            'vat_amount'      => $totals['vat_amount'],
            'total_amount'    => $totals['total_amount'],
            'description'     => sanitize_textarea_field($req->get_param('description') ?? ''),
        ]);
        $invoice_id = (int) $wpdb->insert_id;
        self::_save_items($invoice_id, $items);
        return new WP_REST_Response(['success' => true, 'id' => $invoice_id, 'invoice_no' => $inv_no], 201);
    }

    public static function update_invoice(WP_REST_Request $req): WP_REST_Response {
        global $wpdb;
        $id     = (int) $req->get_param('id');
        $status = $wpdb->get_var($wpdb->prepare("SELECT status FROM {$wpdb->prefix}ai_purchase_invoices WHERE id=%d", $id));
        if ($status !== 'draft') return new WP_REST_Response(['success' => false, 'message' => 'فقط پیش‌نویس ویرایش‌پذیر است'], 400);

        $existing = $wpdb->get_row($wpdb->prepare(
            "SELECT warehouse_id, project_id FROM {$wpdb->prefix}ai_purchase_invoices WHERE id=%d", $id
        ), ARRAY_A);
        $uid = acl_current_user_id();
        $deny = acl_deny_scope( $uid, 'warehouse', $existing['warehouse_id'] ? (int)$existing['warehouse_id'] : null, 'purchase.invoices.edit' );
        if ( $deny ) return $deny;
        $deny = acl_deny_scope( $uid, 'project', $existing['project_id'] ? (int)$existing['project_id'] : null, 'purchase.invoices.edit' );
        if ( $deny ) return $deny;

        $wh = $req->get_param('warehouse_id') ? (int) $req->get_param('warehouse_id') : null;
        $pj = $req->get_param('project_id')  ? (int) $req->get_param('project_id')  : null;
        $deny = acl_deny_scope( $uid, 'warehouse', $wh, 'purchase.invoices.edit' );
        if ( $deny ) return $deny;
        $deny = acl_deny_scope( $uid, 'project', $pj, 'purchase.invoices.edit' );
        if ( $deny ) return $deny;

        $items  = $req->get_param('items') ?? [];
        $totals = self::_calculate_totals($items);

        $wpdb->update($wpdb->prefix . 'ai_purchase_invoices', array_merge([
            'supplier_id'   => $req->get_param('supplier_id')  ? (int) $req->get_param('supplier_id')  : null,
            'project_id'    => $req->get_param('project_id')   ? (int) $req->get_param('project_id')   : null,
            'warehouse_id'  => $req->get_param('warehouse_id') ? (int) $req->get_param('warehouse_id') : null,
            'ref_number'    => sanitize_text_field($req->get_param('ref_number')    ?? ''),
            'payment_terms' => (int) ($req->get_param('payment_terms') ?? 0),
            'invoice_date'  => sanitize_text_field($req->get_param('invoice_date') ?: date('Y-m-d')),
            'description'   => sanitize_textarea_field($req->get_param('description') ?? ''),
        ], $totals), ['id' => $id]);

        $wpdb->delete($wpdb->prefix . 'ai_purchase_invoice_items', ['invoice_id' => $id]);
        self::_save_items($id, $items);
        return new WP_REST_Response(['success' => true], 200);
    }

    public static function delete_invoice(WP_REST_Request $req): WP_REST_Response {
        global $wpdb;
        $id = (int) $req->get_param('id');
        $row = $wpdb->get_row($wpdb->prepare(
            "SELECT status, warehouse_id, project_id FROM {$wpdb->prefix}ai_purchase_invoices WHERE id=%d", $id
        ), ARRAY_A);
        if (!$row) return new WP_REST_Response(['success' => false, 'message' => 'یافت نشد'], 404);
        $uid = acl_current_user_id();
        $deny = acl_deny_scope( $uid, 'warehouse', $row['warehouse_id'] ? (int)$row['warehouse_id'] : null, 'purchase.invoices.edit' );
        if ( $deny ) return $deny;
        $deny = acl_deny_scope( $uid, 'project', $row['project_id'] ? (int)$row['project_id'] : null, 'purchase.invoices.edit' );
        if ( $deny ) return $deny;
        if ($row['status'] === 'finalized') {
            return new WP_REST_Response(['success' => false, 'message' => 'فاکتور نهایی‌شده حذف نمی‌شود'], 400);
        }
        $wpdb->delete($wpdb->prefix . 'ai_purchase_invoice_items', ['invoice_id' => $id]);
        $wpdb->delete($wpdb->prefix . 'ai_purchase_invoices',      ['id'         => $id]);
        return new WP_REST_Response(['success' => true], 200);
    }

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

        $invoice = $wpdb->get_row($wpdb->prepare(
            "SELECT i.*, s.name AS supplier_name
             FROM {$wpdb->prefix}ai_purchase_invoices i
             LEFT JOIN {$wpdb->prefix}ai_purchase_suppliers s ON s.id = i.supplier_id
             WHERE i.id=%d", $id
        ), ARRAY_A);

        if (!$invoice) return new WP_REST_Response(['success' => false, 'message' => 'یافت نشد'], 404);
        $uid = acl_current_user_id();
        $deny = acl_deny_scope( $uid, 'warehouse', $invoice['warehouse_id'] ? (int)$invoice['warehouse_id'] : null, 'purchase.invoices.finalize' );
        if ( $deny ) return $deny;
        $deny = acl_deny_scope( $uid, 'project', $invoice['project_id'] ? (int)$invoice['project_id'] : null, 'purchase.invoices.finalize' );
        if ( $deny ) return $deny;
        if ($invoice['status'] !== 'draft') return new WP_REST_Response(['success' => false, 'message' => 'فقط پیش‌نویس نهایی می‌شود'], 400);

        require_once ACC_PATH . 'includes/helpers/acc-event-engine.php';
        $payload = [
            'invoice_id'    => $id,
            'invoice_no'    => $invoice['invoice_no'],
            'supplier_name' => $invoice['supplier_name'] ?? '',
            'net_amount'    => (float) $invoice['net_amount'],
            'vat_amount'    => (float) $invoice['vat_amount'],
            'discount'      => (float) $invoice['discount_amount'],
            'total_amount'  => (float) $invoice['total_amount'],
        ];

        $result = Acc_Event_Engine::emit_and_post([
            'event_type'      => 'PURCHASE_INVOICE',
            'amount'          => (float) $invoice['total_amount'],
            'payload'         => $payload,
            'reference_type'  => 'purchase_invoice',
            'reference_id'    => $id,
            'idempotency_key' => 'PUR_INV_' . $id,
            'source_module'   => 'purchase',
        ]);

        if (!$result['success']) {
            return new WP_REST_Response(['success' => false, 'message' => $result['message'] ?? 'خطا'], 400);
        }

        $event_id = (int) $result['event_id'];
        $msg = $result['message'] ?? 'سند صادر شد';

        $wpdb->update($wpdb->prefix . 'ai_purchase_invoices', [
            'status'       => 'finalized',
            'acc_event_id' => $event_id,
        ], ['id' => $id]);

        // ── ادغام انبار: ثبت خودکار سند ورود ──────────────────
        if ( class_exists('InventoryIntegration') ) {
            InventoryIntegration::on_purchase_finalized( $id );
        }

        return new WP_REST_Response(['success' => true, 'message' => $msg, 'event_id' => $event_id], 200);
    }

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

    public static function report_summary(WP_REST_Request $req): array {
        global $wpdb;
        $from = sanitize_text_field($req->get_param('date_from') ?? date('Y-01-01'));
        $to   = sanitize_text_field($req->get_param('date_to')   ?? date('Y-m-d'));

        $summary = $wpdb->get_row($wpdb->prepare(
            "SELECT COUNT(*) AS total_count,
                    SUM(CASE WHEN status='finalized' THEN 1         ELSE 0 END) AS finalized_count,
                    SUM(CASE WHEN status='finalized' THEN total_amount ELSE 0 END) AS total_purchase,
                    SUM(CASE WHEN status='finalized' THEN vat_amount   ELSE 0 END) AS total_vat,
                    SUM(CASE WHEN status='finalized' THEN net_amount   ELSE 0 END) AS total_net
             FROM {$wpdb->prefix}ai_purchase_invoices
             WHERE invoice_date BETWEEN %s AND %s", $from, $to
        ), ARRAY_A);

        $by_supplier = $wpdb->get_results($wpdb->prepare(
            "SELECT s.name AS supplier_name, COUNT(*) AS invoice_count, SUM(i.total_amount) AS total
             FROM {$wpdb->prefix}ai_purchase_invoices i
             LEFT JOIN {$wpdb->prefix}ai_purchase_suppliers s ON s.id=i.supplier_id
             WHERE i.status='finalized' AND i.invoice_date BETWEEN %s AND %s
             GROUP BY i.supplier_id, s.name ORDER BY total DESC LIMIT 10", $from, $to
        ), ARRAY_A);

        return ['success' => true, 'summary' => $summary, 'by_supplier' => $by_supplier ?: []];
    }

    private static function _calculate_totals(array $items): array {
        $subtotal = $disc_total = $net = $vat = 0;
        foreach ($items as $item) {
            $qty   = (float)($item['quantity']??1);   $price = (float)($item['unit_price']??0);
            $dp    = (float)($item['discount_pct']??0); $vr  = (float)($item['vat_rate']??9);
            $base  = $qty * $price; $d = $base*($dp/100); $n = $base-$d; $v = $n*($vr/100);
            $subtotal += $base; $disc_total += $d; $net += $n; $vat += $v;
        }
        return ['subtotal'=>round($subtotal,4),'discount_amount'=>round($disc_total,4),'net_amount'=>round($net,4),'vat_amount'=>round($vat,4),'total_amount'=>round($net+$vat,4)];
    }

    private static function _save_items(int $invoice_id, array $items): void {
        global $wpdb;
        foreach ($items as $i => $item) {
            $qty=$item['quantity']??1; $price=$item['unit_price']??0;
            $dp=$item['discount_pct']??0; $vr=$item['vat_rate']??9;
            $base=$qty*$price; $d=$base*($dp/100); $n=$base-$d; $v=$n*($vr/100);
            $wpdb->insert($wpdb->prefix.'ai_purchase_invoice_items',[
                'invoice_id'=>$invoice_id,'product_id'=>!empty($item['product_id'])?(int)$item['product_id']:null,
                'description'=>sanitize_text_field($item['description']??''),
                'quantity'=>$qty,'unit_price'=>$price,'discount_pct'=>$dp,'vat_rate'=>$vr,
                'line_net'=>round($n,4),'line_vat'=>round($v,4),'line_total'=>round($n+$v,4),'sort_order'=>$i,
            ]);
        }
    }
}
