<?php
/**
 * Qeshm_Wholesale — B2B عمده‌فروشی منطقه آزاد → مغازه / توزیع‌کننده
 * استاندارد: Price List · MOQ · Tier · PO · Incoterms · Credit Terms
 */
if ( ! defined( 'ABSPATH' ) ) exit;

class Qeshm_Wholesale {

    public const TIERS = [
        'retailer'    => [ 'label' => 'خرده‌فروش / مغازه',     'discount_note' => 'قیمت پایه B2B' ],
        'distributor' => [ 'label' => 'عمده‌فروش / توزیع',     'discount_note' => 'تخفیف حجم بالاتر' ],
        'vip'         => [ 'label' => 'VIP / زنجیره',          'discount_note' => 'بهترین نرخ' ],
    ];

    public const ZONES = [
        'qeshm_ftz' => 'منطقه آزاد قشم',
        'kish_ftz'   => 'منطقه آزاد کیش',
        'chabahar'  => 'چابهار',
        'mainland'  => 'سرزمین اصلی',
    ];

    public const INCOTERMS = [
        'EXW' => 'EXW — تحویل انبار قشم',
        'FCA' => 'FCA — تحویل به حمل‌کننده',
        'DAP' => 'DAP — تحویل در مقصد',
    ];

    public const PAYMENT_TERMS = [
        'prepaid'  => 'پیش‌پرداخت ۱۰۰٪',
        'cod'      => 'پرداخت در محل',
        'net_15'   => 'Net 15',
        'net_30'   => 'Net 30 (اعتبار)',
    ];

    public const ORDER_STATUS = [
        'draft'      => 'پیش‌نویس',
        'submitted'  => 'ثبت‌شده',
        'confirmed'  => 'تأیید شده',
        'picking'    => 'جمع‌آوری',
        'shipped'    => 'ارسال‌شده',
        'delivered'  => 'تحویل‌شده',
        'cancelled'  => 'لغو',
    ];

    public static function accounts_table(): string {
        global $wpdb;
        return $wpdb->prefix . 'wholesale_accounts';
    }

    public static function products_table(): string {
        global $wpdb;
        return $wpdb->prefix . 'wholesale_products';
    }

    public static function prices_table(): string {
        global $wpdb;
        return $wpdb->prefix . 'wholesale_prices';
    }

    public static function orders_table(): string {
        global $wpdb;
        return $wpdb->prefix . 'wholesale_orders';
    }

    public static function applications_table(): string {
        global $wpdb;
        return $wpdb->prefix . 'wholesale_applications';
    }

    public static function can_buyer( int $uid ): bool {
        if ( acl_user_is_super_admin( $uid ) || acl_user_can( $uid, 'wholesale.manage' ) ) {
            return true;
        }
        if ( ! acl_user_can( $uid, 'wholesale.buy' ) ) {
            return false;
        }
        $acc = self::get_account_by_user( $uid );
        return $acc && ( $acc['status'] ?? '' ) === 'approved';
    }

    public static function can_manage( int $uid ): bool {
        return acl_user_is_super_admin( $uid )
            || acl_user_can( $uid, 'wholesale.manage' )
            || acl_user_can( $uid, 'shop.manage' );
    }

    public static function get_account_by_user( int $user_id ): ?array {
        global $wpdb;
        $t = self::accounts_table();
        if ( $wpdb->get_var( "SHOW TABLES LIKE '{$t}'" ) !== $t ) {
            return null;
        }
        $row = $wpdb->get_row( $wpdb->prepare(
            "SELECT * FROM {$t} WHERE user_id = %d", $user_id
        ), ARRAY_A );
        return $row ? self::fmt_account( $row ) : null;
    }

    public static function fmt_account( array $row ): array {
        $row['tier'] = $row['tier'] ?? 'retailer';
        $row['tier_label'] = self::TIERS[ $row['tier'] ]['label'] ?? $row['tier'];
        $row['zone_label'] = self::ZONES[ $row['zone'] ?? '' ] ?? ( $row['zone'] ?? '' );
        return $row;
    }

    public static function list_catalog( ?string $tier = null, ?string $category = null ): array {
        global $wpdb;
        $pt = self::products_table();
        $pr = self::prices_table();
        $w  = [ 'p.is_active = 1' ];
        $args = [];
        if ( $category ) {
            $w[] = 'p.category = %s';
            $args[] = sanitize_key( $category );
        }
        $sql = "SELECT p.* FROM {$pt} p WHERE " . implode( ' AND ', $w ) . ' ORDER BY p.category, p.sort_order, p.id';
        $products = $args ? $wpdb->get_results( $wpdb->prepare( $sql, ...$args ), ARRAY_A ) : $wpdb->get_results( $sql, ARRAY_A );
        $out = [];
        foreach ( $products ?: [] as $p ) {
            $out[] = self::fmt_product( $p, $tier );
        }
        return $out;
    }

    public static function fmt_product( array $p, ?string $tier = null ): array {
        global $wpdb;
        $pr = self::prices_table();
        $pid = (int) $p['id'];
        $prices = $wpdb->get_results( $wpdb->prepare(
            "SELECT * FROM {$pr} WHERE product_id = %d ORDER BY tier, min_qty", $pid
        ), ARRAY_A ) ?: [];

        $tier_prices = [];
        foreach ( $prices as $row ) {
            $tier_prices[ $row['tier'] ][] = [
                'min_qty'    => (int) $row['min_qty'],
                'unit_price' => (float) $row['unit_price'],
            ];
        }

        $resolved = $tier ? self::resolve_price( $prices, $tier, (int) $p['moq'] ) : null;

        return [
            'id'           => $pid,
            'sku'          => $p['sku'],
            'name'         => $p['name'],
            'category'     => $p['category'],
            'category_label' => self::category_label( $p['category'] ),
            'unit'         => $p['unit'],
            'moq'          => (int) $p['moq'],
            'origin_zone'  => $p['origin_zone'],
            'origin_label' => self::ZONES[ $p['origin_zone'] ?? '' ] ?? '',
            'description'  => $p['description'],
            'image_emoji'  => $p['image_emoji'] ?? '📦',
            'stock_qty'    => (int) ( $p['stock_qty'] ?? 0 ),
            'prices'       => $tier_prices,
            'your_price'   => $resolved['unit_price'] ?? null,
            'price_breaks' => $tier ? ( $tier_prices[ $tier ] ?? [] ) : [],
        ];
    }

    public static function resolve_price( array $price_rows, string $tier, int $qty ): array {
        $candidates = array_filter( $price_rows, static fn( $r ) => ( $r['tier'] ?? '' ) === $tier && (int) $r['min_qty'] <= $qty );
        if ( ! $candidates ) {
            $candidates = array_filter( $price_rows, static fn( $r ) => ( $r['tier'] ?? '' ) === $tier );
        }
        usort( $candidates, static fn( $a, $b ) => (int) $b['min_qty'] <=> (int) $a['min_qty'] );
        $best = $candidates[0] ?? null;
        return [
            'unit_price' => $best ? (float) $best['unit_price'] : 0,
            'min_qty'    => $best ? (int) $best['min_qty'] : 1,
        ];
    }

    public static function category_label( string $cat ): string {
        $map = [
            'electronics' => 'الکترونیک و دیجیتال',
            'cosmetics'   => 'آرایشی و بهداشتی',
            'food'        => 'مواد غذایی',
            'textile'     => 'پوشاک و منسوجات',
            'home'        => 'خانه و آشپزخانه',
            'appliances'  => 'لوازم خانگی',
            'pharma'      => 'دارو و مکمل',
            'auto'        => 'لوازم خودرو',
            'office'      => 'اداری و مصرفی',
            'other'       => 'سایر',
        ];
        return $map[ $cat ] ?? $cat;
    }

    public static function category_counts(): array {
        global $wpdb;
        $pt = self::products_table();
        $rows = $wpdb->get_results(
            "SELECT category, COUNT(*) AS cnt FROM {$pt} WHERE is_active=1 GROUP BY category ORDER BY category",
            ARRAY_A
        ) ?: [];
        $out = [];
        foreach ( $rows as $r ) {
            $cat = $r['category'];
            $out[] = [
                'key'   => $cat,
                'label' => self::category_label( $cat ),
                'count' => (int) $r['cnt'],
            ];
        }
        return $out;
    }

    /**
     * @return array{items: array, total: int, page: int, per_page: int}
     */
    public static function search_catalog( ?string $tier, array $opts = [] ): array {
        global $wpdb;
        $pt = self::products_table();
        $page     = max( 1, (int) ( $opts['page'] ?? 1 ) );
        $per_page = min( 100, max( 6, (int) ( $opts['per_page'] ?? 24 ) ) );
        $offset   = ( $page - 1 ) * $per_page;

        $w    = [ 'p.is_active = 1' ];
        $args = [];

        if ( ! empty( $opts['category'] ) ) {
            $w[] = 'p.category = %s';
            $args[] = sanitize_key( $opts['category'] );
        }
        if ( ! empty( $opts['origin'] ) ) {
            $w[] = 'p.origin_zone = %s';
            $args[] = sanitize_key( $opts['origin'] );
        }
        if ( ! empty( $opts['q'] ) ) {
            $q = '%' . $wpdb->esc_like( sanitize_text_field( $opts['q'] ) ) . '%';
            $w[] = '(p.name LIKE %s OR p.sku LIKE %s OR p.description LIKE %s)';
            $args[] = $q;
            $args[] = $q;
            $args[] = $q;
        }
        if ( ! empty( $opts['in_stock'] ) ) {
            $w[] = 'p.stock_qty > 0';
        }

        $where = implode( ' AND ', $w );
        $count_sql = "SELECT COUNT(*) FROM {$pt} p WHERE {$where}";
        $total = $args
            ? (int) $wpdb->get_var( $wpdb->prepare( $count_sql, ...$args ) )
            : (int) $wpdb->get_var( $count_sql );

        $sort = sanitize_key( $opts['sort'] ?? 'default' );
        $order = match ( $sort ) {
            'price_asc'  => 'p.sort_order ASC, p.id ASC',
            'price_desc' => 'p.sort_order ASC, p.id DESC',
            'moq_asc'    => 'p.moq ASC, p.name ASC',
            'moq_desc'   => 'p.moq DESC, p.name ASC',
            'name'       => 'p.name ASC',
            'stock'      => 'p.stock_qty DESC, p.name ASC',
            default      => 'p.category ASC, p.sort_order ASC, p.id ASC',
        };

        $sql = "SELECT p.* FROM {$pt} p WHERE {$where} ORDER BY {$order} LIMIT %d OFFSET %d";
        $args[] = $per_page;
        $args[] = $offset;
        $products = $wpdb->get_results( $wpdb->prepare( $sql, ...$args ), ARRAY_A ) ?: [];

        $items = [];
        foreach ( $products as $p ) {
            $items[] = self::fmt_product( $p, $tier );
        }

        return [
            'items'    => $items,
            'total'    => $total,
            'page'     => $page,
            'per_page' => $per_page,
            'pages'    => (int) ceil( $total / $per_page ),
        ];
    }

    public static function create_application( array $data ): array {
        global $wpdb;
        $business = sanitize_text_field( $data['business_name'] ?? '' );
        $phone    = sanitize_text_field( $data['phone'] ?? '' );
        if ( ! $business || ! $phone ) {
            return [ 'success' => false, 'message' => 'نام کسب‌وکار و تلفن الزامی است' ];
        }
        $wpdb->insert( self::applications_table(), [
            'business_name'  => $business,
            'business_type'  => sanitize_key( $data['business_type'] ?? 'retailer' ),
            'contact_name'   => sanitize_text_field( $data['contact_name'] ?? '' ),
            'phone'          => $phone,
            'email'          => sanitize_email( $data['email'] ?? '' ),
            'city'           => sanitize_text_field( $data['city'] ?? '' ),
            'zone'           => sanitize_key( $data['zone'] ?? 'mainland' ),
            'tax_id'         => sanitize_text_field( $data['tax_id'] ?? '' ),
            'address'        => sanitize_textarea_field( $data['address'] ?? '' ),
            'notes'          => sanitize_textarea_field( $data['notes'] ?? '' ),
            'status'         => 'pending',
            'created_at'     => current_time( 'mysql' ),
        ] );
        return [ 'success' => true, 'id' => (int) $wpdb->insert_id ];
    }

    public static function create_order( int $user_id, array $data ): array {
        if ( ! self::can_buyer( $user_id ) ) {
            return [ 'success' => false, 'message' => 'حساب عمده‌فروشی تأیید نشده' ];
        }
        $account = self::get_account_by_user( $user_id );
        if ( ! $account || ( $account['status'] ?? '' ) !== 'approved' ) {
            if ( ! self::can_manage( $user_id ) ) {
                return [ 'success' => false, 'message' => 'حساب عمده‌فروشی تأیید نشده' ];
            }
            return [ 'success' => false, 'message' => 'مدیر بدون حساب خریدار نمی‌تواند سفارش ثبت کند' ];
        }

        $items = $data['items'] ?? [];
        if ( ! is_array( $items ) || ! $items ) {
            return [ 'success' => false, 'message' => 'سبد خالی است' ];
        }

        global $wpdb;
        $lines    = [];
        $subtotal = 0;
        $tier     = $account['tier'] ?? 'retailer';

        foreach ( $items as $it ) {
            $pid = (int) ( $it['product_id'] ?? 0 );
            $qty = (int) ( $it['qty'] ?? 0 );
            if ( ! $pid || $qty <= 0 ) continue;

            $p = $wpdb->get_row( $wpdb->prepare(
                "SELECT * FROM " . self::products_table() . " WHERE id = %d AND is_active = 1", $pid
            ), ARRAY_A );
            if ( ! $p ) {
                return [ 'success' => false, 'message' => "محصول #{$pid} یافت نشد" ];
            }
            if ( $qty < (int) $p['moq'] ) {
                return [ 'success' => false, 'message' => "حداقل سفارش {$p['name']}: {$p['moq']} {$p['unit']}" ];
            }
            if ( (int) $p['stock_qty'] < $qty ) {
                return [ 'success' => false, 'message' => "موجودی کافی نیست: {$p['name']}" ];
            }

            $prices = $wpdb->get_results( $wpdb->prepare(
                "SELECT * FROM " . self::prices_table() . " WHERE product_id = %d", $pid
            ), ARRAY_A ) ?: [];
            $resolved = self::resolve_price( $prices, $tier, $qty );
            $line_total = $resolved['unit_price'] * $qty;
            $subtotal += $line_total;
            $lines[] = [
                'product_id'  => $pid,
                'sku'         => $p['sku'],
                'name'        => $p['name'],
                'unit'        => $p['unit'],
                'qty'         => $qty,
                'unit_price'  => $resolved['unit_price'],
                'line_total'  => $line_total,
            ];
        }

        if ( ! $lines ) {
            return [ 'success' => false, 'message' => 'هیچ قلم معتبری نیست' ];
        }

        $shipping = (float) ( $data['shipping_cost'] ?? 0 );
        $total    = $subtotal + $shipping;
        $key      = 'WS-' . strtoupper( substr( md5( uniqid( (string) $user_id, true ) ), 0, 8 ) );

        $wpdb->insert( self::orders_table(), [
            'order_key'      => $key,
            'user_id'        => $user_id,
            'account_id'     => (int) $account['id'],
            'tier'           => $tier,
            'items_json'     => wp_json_encode( $lines, JSON_UNESCAPED_UNICODE ),
            'subtotal'       => $subtotal,
            'shipping_cost'  => $shipping,
            'total'          => $total,
            'currency'       => 'IRR',
            'po_number'      => sanitize_text_field( $data['po_number'] ?? '' ) ?: null,
            'incoterm'       => sanitize_key( $data['incoterm'] ?? 'DAP' ),
            'payment_terms'  => sanitize_key( $data['payment_terms'] ?? 'prepaid' ),
            'ship_to_address'=> sanitize_textarea_field( $data['ship_to_address'] ?? $account['address'] ?? '' ),
            'ship_to_city'   => sanitize_text_field( $data['ship_to_city'] ?? $account['city'] ?? '' ),
            'customer_note'  => sanitize_textarea_field( $data['customer_note'] ?? '' ),
            'status'         => 'submitted',
            'created_at'     => current_time( 'mysql' ),
        ] );
        $order_id = (int) $wpdb->insert_id;

        foreach ( $lines as $ln ) {
            $wpdb->query( $wpdb->prepare(
                "UPDATE " . self::products_table() . " SET stock_qty = GREATEST(0, stock_qty - %d) WHERE id = %d",
                $ln['qty'], $ln['product_id']
            ) );
        }

        return [
            'success'   => true,
            'order_id'  => $order_id,
            'order_key' => $key,
            'total'     => $total,
        ];
    }

    public static function list_orders( int $user_id, bool $all = false ): array {
        global $wpdb;
        $t = self::orders_table();
        if ( $all && self::can_manage( $user_id ) ) {
            $rows = $wpdb->get_results(
                "SELECT * FROM {$t} ORDER BY id DESC LIMIT 100", ARRAY_A
            ) ?: [];
        } else {
            $rows = $wpdb->get_results( $wpdb->prepare(
                "SELECT * FROM {$t} WHERE user_id = %d ORDER BY id DESC LIMIT 50", $user_id
            ), ARRAY_A ) ?: [];
        }
        return array_map( [ __CLASS__, 'fmt_order' ], $rows );
    }

    public static function fmt_order( array $row ): array {
        $row['items'] = json_decode( $row['items_json'] ?? '[]', true ) ?: [];
        unset( $row['items_json'] );
        $row['status_label'] = self::ORDER_STATUS[ $row['status'] ?? '' ] ?? $row['status'];
        $row['incoterm_label'] = self::INCOTERMS[ $row['incoterm'] ?? '' ] ?? $row['incoterm'];
        $row['payment_label'] = self::PAYMENT_TERMS[ $row['payment_terms'] ?? '' ] ?? $row['payment_terms'];
        return $row;
    }

    public static function stats(): array {
        global $wpdb;
        $pt = self::products_table();
        $ot = self::orders_table();
        $at = self::accounts_table();
        return [
            'products'     => (int) $wpdb->get_var( "SELECT COUNT(*) FROM {$pt} WHERE is_active=1" ),
            'buyers'       => (int) $wpdb->get_var( "SELECT COUNT(*) FROM {$at} WHERE status='approved'" ),
            'orders_month' => (int) $wpdb->get_var(
                "SELECT COUNT(*) FROM {$ot} WHERE created_at >= DATE_SUB(NOW(), INTERVAL 30 DAY)"
            ),
            'zones'        => self::ZONES,
        ];
    }
}
