<?php

namespace SoftminalB2B\Http\Controllers\Concerns;

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

use SoftminalB2B\Pricing\ProductVendor;
use SoftminalB2B\Pricing\VendorContext;

/**
 * Makes a rule controller (price or quantity) ownership-aware, so the same
 * endpoints serve both the marketplace admin and a self-service vendor.
 *
 * Core stays marketplace-agnostic: it learns "this request belongs to vendor N"
 * only through the `smb2b_vendor_context` seam (which the Dokan bridge answers on
 * a vendor-dashboard request). When a vendor is acting, the controller:
 *   - lists only rules that vendor owns (`owner_id`),
 *   - stamps new rules with the vendor's ownership,
 *   - refuses to edit or delete a rule the vendor does not own,
 *   - and accepts only rules scoped to that vendor's own catalogue — the
 *     `vendor` scope for their own id, or a `product` rule whose product they
 *     author (WholesaleX's post_author ownership rule; variations resolve to the
 *     parent first, which `ProductVendor` already does).
 *
 * The admin (the default context) is unaffected and manages every rule.
 */
trait VendorOwnedRules
{
    private const OWNER_TYPE_VENDOR = 'vendor';

    /**
     * The acting vendor id, or 0 when the request is the marketplace admin.
     */
    protected function actingVendorId(): int
    {
        $context = VendorContext::current();

        return !empty($context['is_vendor']) ? (int) $context['vendor_id'] : 0;
    }

    /**
     * Restrict a list query to the acting vendor's own rules. A no-op for admins.
     *
     * @param mixed $query
     * @return mixed
     */
    protected function scopeToVendor($query)
    {
        $vendorId = $this->actingVendorId();

        if ($vendorId <= 0) {
            return $query;
        }

        return $query
            ->andWhere('owner_type', '=', self::OWNER_TYPE_VENDOR)
            ->andWhere('owner_id', '=', $vendorId);
    }

    /**
     * Stamp the acting vendor's ownership onto a new rule's attributes. Admin
     * rules are left owner-less (null), as before.
     *
     * @param array<string, mixed> $attributes
     * @return array<string, mixed>
     */
    protected function withVendorOwner(array $attributes): array
    {
        $vendorId = $this->actingVendorId();

        if ($vendorId > 0) {
            $attributes['owner_id']   = $vendorId;
            $attributes['owner_type'] = self::OWNER_TYPE_VENDOR;
        }

        return $attributes;
    }

    /**
     * Whether the acting user may manage (edit/delete) an existing rule. Admins
     * always may; a vendor only their own rules.
     *
     * @param object $rule
     */
    protected function mayManageRule($rule): bool
    {
        $vendorId = $this->actingVendorId();

        if ($vendorId <= 0) {
            return true;
        }

        return (int) ($rule->owner_id ?? 0) === $vendorId
            && (string) ($rule->owner_type ?? '') === self::OWNER_TYPE_VENDOR;
    }

    /**
     * Validate that a vendor may create/edit a rule with this scope and target.
     * Returns an error message, or null when allowed (and always null for admins).
     */
    protected function vendorScopeError(string $scope, int $objectId): ?string
    {
        $vendorId = $this->actingVendorId();

        if ($vendorId <= 0) {
            return null;
        }

        // A vendor may price their whole catalogue…
        if ($scope === 'vendor') {
            return $objectId === $vendorId
                ? null
                : __('You can only set pricing for your own store.', 'softminal-b2b-wholesale-for-woocommerce');
        }

        // …or a single product they own (author). Variations resolve to parent.
        if ($scope === 'product') {
            return ProductVendor::for($objectId) === $vendorId
                ? null
                : __('You can only set pricing for your own products.', 'softminal-b2b-wholesale-for-woocommerce');
        }

        // Store-wide, category, tag and per-customer rules span vendors, so a
        // vendor cannot create them.
        return __('You can only set pricing for your own products or store.', 'softminal-b2b-wholesale-for-woocommerce');
    }
}
