<?php
/**
 * Plugin Name: Pilasa Production Requests
 * Description: Production request button for out-of-stock WooCommerce products, with customer notes and an admin request-management dashboard.
 * Version: 1.0.1
 * Author: pilasa.ir
 * Author URI: https://pilasa.ir
 * Text Domain: pilasa-production-requests
 * Requires PHP: 7.4
 */
if (!defined('ABSPATH')) exit;

final class Pilasa_Production_Requests {
    const VERSION = '1.0.1';
    const OPTION = 'pilasa_pr_settings';
    const NONCE_ACTION = 'pilasa_pr_submit_request';
    private static $instance = null;
    public static function instance() { return self::$instance ?: (self::$instance = new self()); }
    private function __construct() {
        add_action('admin_menu', [$this, 'admin_menu']);
        add_action('admin_init', [$this, 'register_settings']);
        add_action('admin_init', [$this, 'maybe_upgrade_schema']);
        add_action('wp_enqueue_scripts', [$this, 'register_assets']);
        add_shortcode('pilasa_production_request', [$this, 'shortcode']);
        add_action('admin_post_pilasa_pr_submit', [$this, 'handle_submit']);
        add_action('admin_post_nopriv_pilasa_pr_submit', [$this, 'handle_guest_submit']);
        add_action('admin_post_pilasa_pr_update', [$this, 'handle_admin_update']);
        add_filter('manage_users_columns', [$this, 'maybe_noop_user_columns']);
    }
    private function table() { global $wpdb; return $wpdb->prefix . 'pilasa_production_requests'; }
    public static function activate_plugin() { self::instance()->activate(); }
    public function activate() {
        global $wpdb;
        require_once ABSPATH . 'wp-admin/includes/upgrade.php';
        $table = $this->table(); $charset = $wpdb->get_charset_collate();
        $sql = "CREATE TABLE $table (
            id bigint(20) unsigned NOT NULL AUTO_INCREMENT,
            user_id bigint(20) unsigned NOT NULL,
            product_id bigint(20) unsigned NOT NULL,
            variation_id bigint(20) unsigned NOT NULL DEFAULT 0,
            product_name varchar(255) NOT NULL,
            variation_name varchar(255) NOT NULL DEFAULT '',
            product_url text NOT NULL,
            customer_name varchar(255) NOT NULL DEFAULT '',
            customer_email varchar(190) NOT NULL DEFAULT '',
            customer_phone varchar(100) NOT NULL DEFAULT '',
            request_note longtext NOT NULL,
            status varchar(30) NOT NULL DEFAULT 'new',
            result_note longtext NOT NULL,
            amount decimal(18,2) NULL DEFAULT NULL,
            currency varchar(10) NOT NULL DEFAULT '',
            created_at datetime NOT NULL,
            updated_at datetime NOT NULL,
            completed_at datetime NULL DEFAULT NULL,
            PRIMARY KEY  (id),
            KEY user_id (user_id),
            KEY product_id (product_id),
            KEY status (status),
            KEY created_at (created_at)
        ) $charset;";
        dbDelta($sql);
        if (!get_option(self::OPTION)) add_option(self::OPTION, ['categories'=>[], 'notice'=>'زمان تولید محصول فوق 10 الی 15 روز کاری زمان خواهد برد. با سپاس']);
        update_option('pilasa_pr_db_version', self::VERSION);
    }
    public function maybe_upgrade_schema() {
        if (get_option('pilasa_pr_db_version') !== self::VERSION) $this->activate();
    }
    private function existing_request($user_id, $product_id, $variation_id = 0) {
        global $wpdb;
        // A customer may submit again only after the earlier request was cancelled.
        return $wpdb->get_var($wpdb->prepare(
            "SELECT id FROM {$this->table()} WHERE user_id = %d AND product_id = %d AND variation_id = %d AND status <> 'cancelled' ORDER BY id DESC LIMIT 1",
            $user_id, $product_id, $variation_id
        ));
    }
    private function settings() {
        $s = get_option(self::OPTION, []);
        return wp_parse_args(is_array($s) ? $s : [], ['categories'=>[], 'notice'=>'زمان تولید محصول فوق 10 الی 15 روز کاری زمان خواهد برد. با سپاس']);
    }
    public function register_settings() { register_setting('pilasa_pr_settings_group', self::OPTION, [$this, 'sanitize_settings']); }
    public function sanitize_settings($input) {
        $out = $this->settings();
        $out['categories'] = isset($input['categories']) ? array_values(array_unique(array_filter(array_map('absint', (array)$input['categories'])))) : [];
        $out['notice'] = isset($input['notice']) ? sanitize_textarea_field($input['notice']) : '';
        return $out;
    }
    public function admin_menu() {
        add_menu_page('درخواست‌های تولید', 'درخواست‌های تولید', 'manage_woocommerce', 'pilasa-production-requests', [$this, 'requests_page'], 'dashicons-clipboard', 56);
        add_submenu_page('pilasa-production-requests', 'درخواست‌ها', 'همه درخواست‌ها', 'manage_woocommerce', 'pilasa-production-requests', [$this, 'requests_page']);
        add_submenu_page('pilasa-production-requests', 'تنظیمات', 'تنظیمات', 'manage_woocommerce', 'pilasa-production-settings', [$this, 'settings_page']);
    }
    public function register_assets() {
        wp_register_style('pilasa-pr-front', plugins_url('assets/frontend.css', __FILE__), [], self::VERSION);
        wp_register_script('pilasa-pr-front', plugins_url('assets/frontend.js', __FILE__), [], self::VERSION, true);
    }
    private function category_allowed($product) {
        if (!$product || !is_a($product, 'WC_Product')) return false;
        $cats = array_map('absint', (array)$this->settings()['categories']);
        if (!$cats) return false;
        $product_id = $product->get_parent_id() ?: $product->get_id();
        foreach (wp_get_post_terms($product_id, 'product_cat', ['fields'=>'ids']) as $cat_id) {
            foreach ($cats as $allowed) {
                if ((int)$cat_id === (int)$allowed || term_is_ancestor_of((int)$allowed, (int)$cat_id, 'product_cat')) return true;
            }
        }
        return false;
    }
    public function shortcode($atts = []) {
        if (!function_exists('wc_get_product') || !is_product()) return '';
        global $product;
        $atts = shortcode_atts(['product_id'=>0, 'label'=>'درخواست سفارش تولید'], $atts, 'pilasa_production_request');
        $pid = absint($atts['product_id']);
        if (!$pid && $product instanceof WC_Product) $pid = $product->get_id();
        $p = wc_get_product($pid);
        if (!$p || $p->is_in_stock() || !$this->category_allowed($p)) return '';
        wp_enqueue_style('pilasa-pr-front'); wp_enqueue_script('pilasa-pr-front');
        $variation_id = isset($_GET['pilasa_variation']) ? absint($_GET['pilasa_variation']) : 0;
        $selected_product = $p;
        if ($p->is_type('variation')) $selected_product = $p;
        $return_url = get_permalink($p->get_parent_id() ?: $p->get_id());
        if (!is_user_logged_in()) {
            $myaccount = function_exists('wc_get_page_permalink') ? wc_get_page_permalink('myaccount') : wp_login_url();
            if (!$myaccount) $myaccount = wp_login_url();
            $login_url = add_query_arg('redirect_to', rawurlencode($return_url), $myaccount);
            return '<div class="pilasa-pr-wrap"><a class="pilasa-pr-button" href="'.esc_url($login_url).'">'.esc_html($atts['label']).'</a><p class="pilasa-pr-login-hint">برای ثبت درخواست، ابتدا وارد حساب کاربری خود شوید یا ثبت‌نام کنید.</p></div>';
        }
        $uid = get_current_user_id();
        $request_product_id = $p->is_type('variation') ? $p->get_parent_id() : $p->get_id();
        $request_variation_id = $p->is_type('variation') ? $p->get_id() : 0;
        $existing_request_id = $this->existing_request($uid, $request_product_id, $request_variation_id);
        if ($existing_request_id) {
            return '<div class="pilasa-pr-wrap"><div class="pilasa-pr-already-requested" role="status">شما قبلاً درخواست خود را ثبت کرده‌اید، لطفاً منتظر تماس همکاران برای هماهنگی‌های سفارش خود باشید.</div></div>';
        }
        $nonce = wp_create_nonce(self::NONCE_ACTION);
        $action = esc_url(admin_url('admin-post.php'));
        ob_start(); ?>
        <div class="pilasa-pr-wrap" data-pilasa-pr>
            <button type="button" class="pilasa-pr-button" data-pr-open><?php echo esc_html($atts['label']); ?></button>
            <form class="pilasa-pr-form" method="post" action="<?php echo $action; ?>" hidden>
                <input type="hidden" name="action" value="pilasa_pr_submit">
                <input type="hidden" name="_wpnonce" value="<?php echo esc_attr($nonce); ?>">
                <input type="hidden" name="product_id" value="<?php echo esc_attr($p->get_id()); ?>">
                <input type="hidden" name="variation_id" value="<?php echo esc_attr($variation_id); ?>">
                <input type="hidden" name="return_url" value="<?php echo esc_url($return_url); ?>">
                <label for="pilasa-pr-note-<?php echo esc_attr($p->get_id()); ?>">توضیحات درخواست خود را یادداشت کنید</label>
                <textarea id="pilasa-pr-note-<?php echo esc_attr($p->get_id()); ?>" name="request_note" rows="4" maxlength="5000" placeholder="توضیحات یا جزئیات موردنظر خود را بنویسید..."></textarea>
                <div class="pilasa-pr-notice"><?php echo nl2br(esc_html($this->settings()['notice'])); ?></div>
                <button type="submit" class="pilasa-pr-submit">ثبت درخواست</button>
                <button type="button" class="pilasa-pr-cancel" data-pr-close>انصراف</button>
            </form>
        </div>
        <?php return ob_get_clean();
    }
    public function handle_guest_submit() {
        $return = isset($_POST['return_url']) ? esc_url_raw(wp_unslash($_POST['return_url'])) : home_url('/');
        $account = function_exists('wc_get_page_permalink') ? wc_get_page_permalink('myaccount') : wp_login_url();
        wp_safe_redirect(add_query_arg('redirect_to', rawurlencode($return), $account ?: wp_login_url())); exit;
    }
    public function handle_submit() {
        if (!is_user_logged_in()) $this->handle_guest_submit();
        if (!isset($_POST['_wpnonce']) || !wp_verify_nonce(sanitize_text_field(wp_unslash($_POST['_wpnonce'])), self::NONCE_ACTION)) wp_die('درخواست معتبر نیست. صفحه را تازه‌سازی کنید.');
        $pid = isset($_POST['product_id']) ? absint($_POST['product_id']) : 0;
        $vid = isset($_POST['variation_id']) ? absint($_POST['variation_id']) : 0;
        $p = wc_get_product($vid ?: $pid);
        if (!$p || $p->is_in_stock() || !$this->category_allowed($p)) $this->redirect_with_message($pid, 'invalid');
        $user = wp_get_current_user();
        $note = isset($_POST['request_note']) ? sanitize_textarea_field(wp_unslash($_POST['request_note'])) : '';
        $product_id = $p->is_type('variation') ? $p->get_parent_id() : $p->get_id();
        $parent = wc_get_product($product_id);
        $variation_name = $p->is_type('variation') ? wc_get_formatted_variation($p, true, false, true) : '';
        $now = current_time('mysql');
        global $wpdb;
        if ($this->existing_request(get_current_user_id(), $product_id, $p->is_type('variation') ? $p->get_id() : 0)) {
            $return = isset($_POST['return_url']) ? esc_url_raw(wp_unslash($_POST['return_url'])) : get_permalink($product_id);
            $this->redirect_with_message($return, 'already');
        }
        $ok = $wpdb->insert($this->table(), [
            'user_id'=>get_current_user_id(), 'product_id'=>$product_id, 'variation_id'=>$p->is_type('variation') ? $p->get_id() : 0,
            'product_name'=>$parent ? $parent->get_name() : $p->get_name(), 'variation_name'=>wp_strip_all_tags($variation_name),
            'product_url'=>get_permalink($product_id), 'customer_name'=>$user->display_name, 'customer_email'=>$user->user_email,
            'customer_phone'=>get_user_meta($user->ID, 'billing_phone', true), 'request_note'=>$note, 'status'=>'new', 'result_note'=>'',
            'amount'=>null, 'currency'=>function_exists('get_woocommerce_currency') ? get_woocommerce_currency() : '', 'created_at'=>$now, 'updated_at'=>$now
        ], ['%d','%d','%d','%s','%s','%s','%s','%s','%s','%s','%s','%s','%s','%s','%s','%s']);
        $return = isset($_POST['return_url']) ? esc_url_raw(wp_unslash($_POST['return_url'])) : get_permalink($product_id);
        if (!$ok) $this->redirect_with_message($return, 'error');
        $this->redirect_with_message($return, 'success');
    }
    private function redirect_with_message($url, $message) {
        if (is_numeric($url)) $url = get_permalink(absint($url));
        if (!$url || !wp_http_validate_url($url)) $url = home_url('/');
        wp_safe_redirect(add_query_arg('pilasa_request', $message, $url)); exit;
    }
    public function handle_admin_update() {
        if (!current_user_can('manage_woocommerce')) wp_die('دسترسی کافی ندارید.');
        $id = isset($_POST['request_id']) ? absint($_POST['request_id']) : 0;
        check_admin_referer('pilasa_pr_update_'.$id);
        $status = isset($_POST['status']) ? sanitize_key($_POST['status']) : 'new';
        if (!in_array($status, ['new','contacted','cancelled','completed'], true)) $status = 'new';
        $note = isset($_POST['result_note']) ? sanitize_textarea_field(wp_unslash($_POST['result_note'])) : '';
        $amount_raw = isset($_POST['amount']) ? wc_format_decimal(wp_unslash($_POST['amount'])) : '';
        $amount = ($amount_raw !== '' && is_numeric($amount_raw) && (float)$amount_raw >= 0) ? (float)$amount_raw : null;
        if ($status === 'completed' && $amount === null) {
            wp_safe_redirect(add_query_arg(['page'=>'pilasa-production-requests','message'=>'need_amount'], admin_url('admin.php'))); exit;
        }
        global $wpdb;
        $data = ['status'=>$status, 'result_note'=>$note, 'amount'=>$amount, 'updated_at'=>current_time('mysql')];
        if ($status === 'completed') $data['completed_at'] = current_time('mysql');
        else $data['completed_at'] = null;
        $wpdb->update($this->table(), $data, ['id'=>$id]);
        wp_safe_redirect(add_query_arg(['page'=>'pilasa-production-requests','updated'=>1], admin_url('admin.php'))); exit;
    }
    public function settings_page() {
        if (!current_user_can('manage_woocommerce')) return;
        $s = $this->settings(); $terms = get_terms(['taxonomy'=>'product_cat','hide_empty'=>false]); ?>
        <div class="wrap pilasa-pr-admin"><h1>تنظیمات درخواست سفارش تولید</h1><form method="post" action="options.php">
        <?php settings_fields('pilasa_pr_settings_group'); ?>
        <div class="pilasa-pr-admin-card"><h2>دسته‌بندی‌های مجاز</h2><p>فقط محصولات ناموجود در دسته‌بندی‌های انتخاب‌شده (و زیر‌دسته‌های آن‌ها) امکان ثبت درخواست خواهند داشت.</p>
        <div class="pilasa-pr-category-list"><?php if (!is_wp_error($terms)) foreach ($terms as $term): ?><label><input type="checkbox" name="<?php echo esc_attr(self::OPTION); ?>[categories][]" value="<?php echo esc_attr($term->term_id); ?>" <?php checked(in_array((int)$term->term_id, array_map('intval',(array)$s['categories']), true)); ?>> <?php echo esc_html($term->name); ?></label><?php endforeach; ?></div></div>
        <div class="pilasa-pr-admin-card"><h2>پیام نکته برای مشتری</h2><textarea class="large-text" rows="3" name="<?php echo esc_attr(self::OPTION); ?>[notice]"><?php echo esc_textarea($s['notice']); ?></textarea><p class="description">متن پیش‌فرض: زمان تولید محصول فوق 10 الی 15 روز کاری زمان خواهد برد. با سپاس</p></div>
        <?php submit_button('ذخیره تنظیمات'); ?></form></div><?php
    }
    public function requests_page() {
        if (!current_user_can('manage_woocommerce')) return;
        global $wpdb; $table = $this->table();
        $filter = isset($_GET['status']) ? sanitize_key($_GET['status']) : '';
        $allowed = ['new','contacted','cancelled','completed'];
        $where = in_array($filter, $allowed, true) ? $wpdb->prepare(' WHERE status = %s', $filter) : '';
        $rows = $wpdb->get_results("SELECT * FROM $table$where ORDER BY created_at DESC LIMIT 500");
        $labels = ['new'=>'جدید','contacted'=>'تماس گرفته شد','cancelled'=>'لغو شده','completed'=>'تکمیل شده']; ?>
        <div class="wrap pilasa-pr-admin"><h1>درخواست‌های تولید</h1><p>درخواست‌های ثبت‌شده مشتریان؛ حداکثر ۵۰۰ درخواست اخیر نمایش داده می‌شود.</p>
        <?php if (isset($_GET['message']) && $_GET['message']==='need_amount'): ?><div class="notice notice-error"><p>برای تکمیل درخواست، ابتدا مبلغ را وارد کنید.</p></div><?php endif; ?>
        <?php if (isset($_GET['updated'])): ?><div class="notice notice-success is-dismissible"><p>درخواست به‌روزرسانی شد.</p></div><?php endif; ?>
        <nav class="pilasa-pr-filters"><a href="<?php echo esc_url(admin_url('admin.php?page=pilasa-production-requests')); ?>">همه</a><?php foreach ($labels as $key=>$label): ?> <a href="<?php echo esc_url(add_query_arg(['page'=>'pilasa-production-requests','status'=>$key], admin_url('admin.php'))); ?>"><?php echo esc_html($label); ?></a><?php endforeach; ?></nav>
        <?php if (!$rows): ?><div class="pilasa-pr-admin-card">هنوز درخواستی ثبت نشده است.</div><?php else: foreach ($rows as $r): $user = get_user_by('id', $r->user_id); ?>
        <section class="pilasa-pr-admin-card pilasa-pr-request-card"><div class="pilasa-pr-request-head"><div><strong>درخواست #<?php echo (int)$r->id; ?> — <?php echo esc_html($r->product_name); ?></strong><?php if ($r->variation_name): ?><div>تنوع: <?php echo esc_html($r->variation_name); ?></div><?php endif; ?></div><span class="pilasa-pr-status status-<?php echo esc_attr($r->status); ?>"><?php echo esc_html($labels[$r->status] ?? $r->status); ?></span></div>
        <div class="pilasa-pr-request-grid"><div><b>مشتری</b><br><?php echo esc_html($r->customer_name); ?></div><div><b>ایمیل</b><br><?php echo esc_html($r->customer_email ?: '—'); ?></div><div><b>تلفن</b><br><?php echo esc_html($r->customer_phone ?: '—'); ?></div><div><b>تاریخ</b><br><?php echo esc_html($r->created_at); ?></div><div><b>حساب کاربری</b><br><?php echo $user ? esc_html($user->user_login) : '—'; ?></div><div><b>محصول</b><br><a href="<?php echo esc_url($r->product_url); ?>" target="_blank" rel="noopener">مشاهده محصول</a></div></div>
        <div class="pilasa-pr-note"><b>توضیحات مشتری</b><p><?php echo $r->request_note !== '' ? nl2br(esc_html($r->request_note)) : 'توضیحی ثبت نشده است.'; ?></p></div>
        <form method="post" action="<?php echo esc_url(admin_url('admin-post.php')); ?>" class="pilasa-pr-update-form"><input type="hidden" name="action" value="pilasa_pr_update"><input type="hidden" name="request_id" value="<?php echo (int)$r->id; ?>"><?php wp_nonce_field('pilasa_pr_update_'.$r->id); ?>
        <label>نتیجه تماس / یادداشت داخلی<textarea name="result_note" rows="2"><?php echo esc_textarea($r->result_note); ?></textarea></label>
        <div class="pilasa-pr-admin-controls"><label>مبلغ نهایی (<?php echo esc_html($r->currency); ?>)<input type="number" min="0" step="0.01" name="amount" value="<?php echo $r->amount !== null ? esc_attr($r->amount) : ''; ?>" placeholder="مبلغ را وارد کنید"></label><label>وضعیت<select name="status"><?php foreach ($labels as $key=>$label): ?><option value="<?php echo esc_attr($key); ?>" <?php selected($r->status, $key); ?>><?php echo esc_html($label); ?></option><?php endforeach; ?></select></label><button class="button button-primary" type="submit">ذخیره تغییرات</button></div>
        <p class="description">برای انتخاب «تکمیل شده»، ثبت مبلغ نهایی الزامی است. این مبلغ در نسخه فعلی برای ثبت داخلی درخواست نگهداری می‌شود و پرداخت آنلاین ایجاد نمی‌کند.</p></form></section>
        <?php endforeach; endif; ?></div><?php
    }
    public function maybe_noop_user_columns($columns) { return $columns; }
}
register_activation_hook(__FILE__, ['Pilasa_Production_Requests', 'activate_plugin']);
add_action('plugins_loaded', function(){ Pilasa_Production_Requests::instance(); });
// Load admin styling only on this plugin's admin pages.
add_action('admin_enqueue_scripts', function($hook) {
    if (strpos((string)$hook, 'pilasa-production') !== false) {
        wp_enqueue_style('pilasa-pr-admin', plugins_url('assets/admin.css', __FILE__), [], Pilasa_Production_Requests::VERSION);
    }
});
