<?php
declare(strict_types=1);

namespace Instinctor\Core;

use Instinctor\Core\Config;
use Instinctor\Core\DB;

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

/**
 * StoreFeatures - Determines which features are visible based on store type and active addons
 * 
 * This is the single source of truth for feature visibility throughout the admin
 */
class StoreFeatures
{
    /**
     * Get current store type
     */
    public static function getStoreType(): string
    {
        return Config::get('instinctor_store_type', 'mixed');
    }

    /**
     * Get active addons
     */
    public static function getActiveAddons(): array
    {
        return Plugin::getActiveAddons();
    }

    /**
     * Check if a specific feature should be visible
     */
    public static function isFeatureEnabled(string $feature): bool
    {
        $storeType = self::getStoreType();
        $addons = self::getActiveAddons();

        // All Access unlocks everything
        if (in_array('all_access', $addons)) {
            return true;
        }

        switch ($feature) {
            // Core features - depend on addons
            case 'shipping':
                return in_array('shipping', $addons);
            
            case 'inventory':
                return in_array('inventory_management', $addons);
            
            case 'downloads':
                return in_array('digital_downloads', $addons);
            
            case 'tax':
                return in_array('tax_management', $addons);

            // Store type specific features
            case 'bookings':
                return in_array('bookings', $addons) || $storeType === 'services' || $storeType === 'salon' || $storeType === 'home_services' || $storeType === 'restaurant';
            
            case 'subscriptions':
                return in_array('subscriptions', $addons) || $storeType === 'subscriptions';

            // Pro features - always check addon
            case 'dropshipping':
            case 'product_bundles':case 'preorders':
            case 'product_addons':
            case 'one_click_checkout':
            case 'volume_discounts':
            case 'smart_checkout':
            case 'loyalty':
            case 'gift_cards':case 'ai_content':
            case 'advanced_analytics':
            case 'software_licensing':
                return in_array($feature, $addons);

            default:
                return false;
        }
    }

    /**
     * Check if store type involves physical products
     */
    /**
     * Customer-facing noun for a completed transaction, adapted to store type.
     * Service/membership stores read "Payment(s)"; product stores read "Order(s)".
     */
    public static function orderNoun(bool $plural = true): string
    {
        if (in_array(self::getStoreType(), ['home_services', 'automotive'], true)) {
            return $plural ? __('Invoices', 'instinctor') : __('Invoice', 'instinctor');
        }
        $serviceLike = in_array(self::getStoreType(), ['memberships', 'services', 'salon', 'instructor'], true);
        if ($serviceLike) {
            return $plural ? __('Payments', 'instinctor') : __('Payment', 'instinctor');
        }
        return $plural ? __('Orders', 'instinctor') : __('Order', 'instinctor');
    }

    /**
     * Heading for the checkout/account summary block. "Order" reads wrong for
     * recurring memberships and services, so adapt to the store type.
     */
    public static function summaryLabel(): string
    {
        switch (self::getStoreType()) {
            case 'memberships':   return __('Membership Summary', 'instinctor');
            case 'subscriptions': return __('Subscription Summary', 'instinctor');
            case 'services':
            case 'salon':
            case 'instructor':
            case 'automotive':
            case 'home_services': return __('Summary', 'instinctor');
            default:              return __('Order Summary', 'instinctor');
        }
    }

    /**
     * Label for cumulative money paid, adapted to store type.
     * Service/membership stores read "Paid"; product stores read "Spent".
     */
    public static function spentLabel(): string
    {
        return in_array(self::getStoreType(), ['memberships', 'services', 'salon', 'instructor', 'home_services', 'automotive'], true)
            ? __('Paid', 'instinctor')
            : __('Spent', 'instinctor');
    }

    /**
     * Admin-workspace label for the orders/transactions list. Membership and
     * subscription stores sell recurring plans, so "Orders" reads wrong.
     */
    public static function orderListLabel(bool $plural = true): string
    {
        switch (self::getStoreType()) {
            case 'memberships':   return $plural ? __('Memberships', 'instinctor')   : __('Membership', 'instinctor');
            case 'subscriptions': return $plural ? __('Subscriptions', 'instinctor') : __('Subscription', 'instinctor');
            case 'services':      return $plural ? __('Bookings', 'instinctor')      : __('Booking', 'instinctor');
            case 'automotive':
            case 'home_services': return $plural ? __('Invoices', 'instinctor')      : __('Invoice', 'instinctor');
            default:              return $plural ? __('Orders', 'instinctor')        : __('Order', 'instinctor');
        }
    }

    /**
     * Noun for a customer record, adapted to store type. Membership stores read
     * "Member(s)", subscription stores "Subscriber(s)"; everything else "Client(s)".
     */
    public static function customerNoun(bool $plural = true, ?string $st = null): string
    {
        switch ($st ?? self::getStoreType()) {
            case 'instructor':
            case 'memberships':   return $plural ? __('Members', 'instinctor')     : __('Member', 'instinctor');
            case 'subscriptions': return $plural ? __('Subscribers', 'instinctor') : __('Subscriber', 'instinctor');
            default:              return $plural ? __('Clients', 'instinctor')      : __('Client', 'instinctor');
        }
    }

    /**
     * Noun for a sellable item, adapted to store type. Membership/subscription
     * stores sell "Plan(s)", services sell "Service(s)"; else "Product(s)".
     */
    public static function productNoun(bool $plural = true, ?string $st = null): string
    {
        switch ($st ?? self::getStoreType()) {
            case 'memberships':
            case 'subscriptions': return $plural ? __('Plans', 'instinctor')    : __('Plan', 'instinctor');
            case 'services':
            case 'salon':
            case 'automotive':
            case 'home_services': return $plural ? __('Services', 'instinctor') : __('Service', 'instinctor');
            case 'instructor':        return $plural ? __('Classes', 'instinctor')  : __('Class', 'instinctor');
            default:              return $plural ? __('Products', 'instinctor') : __('Product', 'instinctor');
        }
    }

    /**
     * Label for the returns/RMA surface. Physical-goods stores get "Returns";
     * memberships and services cancel rather than return, so "Cancellations".
     */
    public static function returnsLabel(): string
    {
        return in_array(self::getStoreType(), ['memberships', 'services', 'salon', 'instructor', 'home_services', 'automotive'], true)
            ? __('Cancellations', 'instinctor')
            : __('Returns', 'instinctor');
    }

    public static function hasPhysicalProducts(): bool
    {
        $storeType = self::getStoreType();
        return in_array($storeType, ['physical_goods', 'mixed', 'subscriptions']);
    }

    /**
     * Check if store type involves digital products
     */
    public static function hasDigitalProducts(): bool
    {
        $storeType = self::getStoreType();
        return in_array($storeType, ['digital_goods', 'mixed']);
    }

    /**
     * Check if store type involves services/bookings
     */
    public static function hasServices(): bool
    {
        $storeType = self::getStoreType();
        return in_array($storeType, ['services', 'salon', 'home_services', 'mixed']);
    }

    /**
     * Check if store type involves subscriptions
     */
    public static function hasSubscriptions(): bool
    {
        $storeType = self::getStoreType();
        return in_array($storeType, ['subscriptions', 'mixed']);
    }

    /**
     * Restaurant store: food ordering with an interactive menu / build-a-pizza,
     * scheduled orders, tipping, and the kitchen board. A distinct type so those
     * restaurant-only surfaces never appear on any other kind of store.
     */
    public static function isRestaurant(): bool
    {
        return self::getStoreType() === 'restaurant';
    }

    /**
     * Beauty / Salon store: appointment-first vertical. Promotes the booking,
     * client and service surfaces and hides ecommerce chrome (products, cart,
     * checkout) unless retail is explicitly switched on. A distinct type so the
     * salon presentation never leaks onto other store kinds.
     */
    public static function isSalon(): bool
    {
        return self::getStoreType() === 'salon';
    }

    /**
     * Whether a salon also sells retail products. Off by default: salons are
     * booking-first, but many sell serums/products, so this re-exposes the
     * Products / Cart surfaces (nav + palette) when switched on in Settings.
     */
    public static function salonRetailEnabled(): bool
    {
        return self::isSalon() && (bool) Config::get('instinctor_salon_retail', false);
    }

    /**
     * Admin-workspace label for the appointments list. Salons read
     * "Appointment(s)"; other booking stores keep "Booking(s)".
     */
    public static function bookingListLabel(bool $plural = true, ?string $st = null): string
    {
        switch ($st ?? self::getStoreType()) {
            case 'restaurant':    return $plural ? __('Reservations', 'instinctor') : __('Reservation', 'instinctor');
            case 'salon':         return $plural ? __('Appointments', 'instinctor') : __('Appointment', 'instinctor');
            case 'home_services': return $plural ? __('Jobs', 'instinctor')         : __('Job', 'instinctor');
            case 'automotive':    return $plural ? __('Work Orders', 'instinctor')  : __('Work Order', 'instinctor');
            case 'instructor':    return $plural ? __('Classes', 'instinctor')      : __('Class', 'instinctor');
            default:              return $plural ? __('Bookings', 'instinctor')     : __('Booking', 'instinctor');
        }
    }

    /**
     * Default call-to-action for the booking block, adapted to store type.
     */
    public static function bookingCtaLabel(): string
    {
        if (self::isRestaurant()) return __('Reserve a Table', 'instinctor');
        if (self::isSalon()) return __('Book Appointment', 'instinctor');
        if (self::isHomeServices()) return __('Schedule', 'instinctor');
        if (self::isAutomotive()) return __('Book Service', 'instinctor');
        return __('Book Now', 'instinctor');
    }

    /**
     * Instructor (Fitness & Lessons) store: recurring group classes on a weekly
     * timetable, memberships / class packs granting access, check-in. The class
     * schedule engine (ClassService) only activates for this type. Store-type
     * key is 'instructor' (the product sub-brand) to avoid colliding with the
     * Salon vertical's "InStudio" marketing name.
     */
    public static function isInstructor(): bool
    {
        return self::getStoreType() === 'instructor';
    }

    /**
     * Home Services / trades store (HVAC, plumbing, electrical, cleaning,
     * landscaping, handyman). Quote-request first, then a scheduled Job, then an
     * Invoice. Hides the storefront / cart unless the trade also sells parts.
     */
    public static function isHomeServices(): bool
    {
        return self::getStoreType() === 'home_services';
    }

    /**
     * Whether a Home Services trade also sells retail parts/products. Off by
     * default (service-first); re-exposes Products / Cart when switched on.
     */
    public static function hsRetailEnabled(): bool
    {
        return self::isHomeServices() && (bool) Config::get('instinctor_hs_retail', false);
    }

    /**
     * Automotive / auto-repair store: appointment-first vertical (Work Orders),
     * estimate -> invoice like Home Services, with an optional parts catalog. A
     * distinct type so the auto presentation never leaks onto other store kinds.
     */
    public static function isAutomotive(): bool
    {
        return self::getStoreType() === 'automotive';
    }

    /**
     * Whether an automotive shop also sells retail parts. Off by default
     * (service-first); re-exposes the Products / Cart surfaces when switched on.
     */
    public static function autoRetailEnabled(): bool
    {
        return self::isAutomotive() && (bool) Config::get('instinctor_auto_retail', false);
    }

    /**
     * Centralized per-store-type admin UI config: nav labels + section
     * visibility for ONE store type. This is the single source of truth the
     * store panel (PHP server render) and instinctor-admin-store.js (live
     * type-switch) both read, so the two can never drift. Retail-gated product
     * visibility for salon / home_services / automotive reads the saved toggle.
     */
    public static function storeUiConfigFor(string $st): array
    {
        $isSalon = $st === 'salon';
        $isHs    = $st === 'home_services';
        $isAuto  = $st === 'automotive';
        $isInstr = $st === 'instructor';
        $isRest  = $st === 'restaurant';

        $salonRetail = (bool) Config::get('instinctor_salon_retail', false);
        $hsRetail    = (bool) Config::get('instinctor_hs_retail', false);
        $autoRetail  = (bool) Config::get('instinctor_auto_retail', false);

        // Products: hidden on services-only and instructor; service-first
        // verticals hide it unless their retail toggle is on.
        $showProducts = ($st !== 'services') && !$isInstr
            && (!$isSalon || $salonRetail)
            && (!$isHs   || $hsRetail)
            && (!$isAuto || $autoRetail);

        return [
            'labels' => [
                'orders'    => ($st === 'memberships') ? self::customerNoun(true, $st) : __('Sales', 'instinctor'),
                'products'  => $isRest ? __('Menu', 'instinctor') : self::productNoun(true, $st),
                'bookings'  => self::bookingListLabel(true, $st),
                'schedule'  => __('Schedule', 'instinctor'),
                'staff'     => __('Staff', 'instinctor'),
            ],
            'show' => [
                'products' => $showProducts,
                'bookings' => in_array($st, ['services', 'mixed', 'salon', 'home_services', 'instructor', 'restaurant', 'automotive'], true),
                'schedule' => $isInstr,
                'staff'    => in_array($st, ['salon', 'services', 'home_services', 'instructor', 'mixed', 'restaurant', 'automotive'], true),
            ],
        ];
    }

    /**
     * Map of every selectable store type -> its storeUiConfigFor(). Output to
     * the store JS so a live store-type switch relabels/shows sections without a
     * reload. Industry types are wrapped so the free WP build drops them from
     * the JS map (a free store can never select an industry).
     */
    public static function storeUiConfigMap(): array
    {
        $types = ['physical_goods', 'digital_goods', 'services', 'subscriptions', 'memberships', 'mixed'];
        
        $map = [];
        foreach ($types as $st) {
            $map[$st] = self::storeUiConfigFor($st);
        }
        return $map;
    }

    /**
     * Get product form fields that should be shown for current store type
     */
    public static function getProductFields(): array
    {
        $storeType = self::getStoreType();
        $addons = self::getActiveAddons();

        // Base fields always shown
        $fields = [
            'name',
            'description',
            'short_description',
            'price',
            'sale_price',
            'images',
            'categories',
            'status',
            'seo',
        ];

        // Physical product fields
        if (self::hasPhysicalProducts() && self::isFeatureEnabled('shipping')) {
            $fields = array_merge($fields, [
                'weight',
                'dimensions',
                'shipping_class',
            ]);
        }

        // Inventory fields
        if (self::isFeatureEnabled('inventory')) {
            $fields = array_merge($fields, [
                'sku',
                'stock_quantity',
                'manage_stock',
                'backorders',
                'low_stock_threshold',
            ]);
        }

        // Digital product fields
        if (self::hasDigitalProducts() && self::isFeatureEnabled('downloads')) {
            $fields = array_merge($fields, [
                'downloadable_files',
                'download_limit',
                'download_expiry',
            ]);
        }

        // Service/Booking fields
        if (self::hasServices() && self::isFeatureEnabled('bookings')) {
            $fields = array_merge($fields, [
                'duration',
                'booking_settings',
            ]);
        }

        // Subscription fields
        if (self::hasSubscriptions() && self::isFeatureEnabled('subscriptions')) {
            $fields = array_merge($fields, [
                'subscription_period',
                'subscription_interval',
                'subscription_trial',
            ]);
        }

        // Addon-specific fields
        if (self::isFeatureEnabled('product_identifiers') || in_array('product_identifiers', $addons)) {
            $fields = array_merge($fields, ['gtin', 'mpn', 'brand']);
        }

        if (self::isFeatureEnabled('preorders') || in_array('preorders', $addons)) {
            $fields = array_merge($fields, ['is_preorder', 'preorder_date']);
        }

        // Product badges are always-on core feature
        $fields = array_merge($fields, ['is_bestseller', 'custom_badge']);

        if (self::isFeatureEnabled('subscriptions') || in_array('subscriptions', $addons)) {
            $fields = array_merge($fields, ['membership_required', 'membership_tiers']);
        }

        if (self::isFeatureEnabled('volume_discounts') || in_array('volume_discounts', $addons)) {
            $fields = array_merge($fields, ['volume_discounts']);
        }

        return array_unique($fields);
    }

    /**
     * Get recommended addons based on current store type
     */
    public static function getRecommendedAddons(): array
    {
        $storeType = self::getStoreType();
        $currentAddons = self::getActiveAddons();

        $recommendations = [
            'physical_goods' => [
                'shipping' => 'Required for shipping physical products',
                'inventory_management' => 'Track stock levels automatically',
                'bundles' => 'Increase average order value',
            ],
            'digital_goods' => [
                'digital_downloads' => 'Required for delivering digital products',
                'software_licensing' => 'Protect and manage software licenses',
                'one_click_checkout' => 'Instant purchases for digital products',
            ],
            'services' => [
                'bookings' => 'Required for appointment scheduling',
                'smart_checkout' => 'Streamlined checkout for services',
            ],
            'subscriptions' => [
                'subscriptions' => 'Required for recurring billing',
                'subscriptions' => 'Add subscriptions, memberships and tiers',
                'loyalty' => 'Reward repeat subscribers',
            ],
            'subscriptions_memberships' => [
                'subscriptions' => 'Required for subscriptions and membership management',
                
                'loyalty' => 'Reward loyal members with points',
                'digital_downloads' => 'Deliver member-exclusive content',
            ],
            'mixed' => [
                'shipping' => 'For physical product delivery',
                'digital_downloads' => 'For digital product delivery',
                'inventory_management' => 'Track physical stock',
                'smart_checkout' => 'Auto-adapts checkout to cart contents',
            ],
        ];

        $storeRecommendations = $recommendations[$storeType] ?? $recommendations['mixed'];
        
        // Filter out already active addons
        return array_filter($storeRecommendations, function($desc, $addon) use ($currentAddons) {
            return !in_array($addon, $currentAddons);
        }, ARRAY_FILTER_USE_BOTH);
    }

    /**
     * Get visibility config for admin pages based on store type and addons
     */
    public static function getAdminPageVisibility(): array
    {
        return [
            'shipping' => self::isFeatureEnabled('shipping'),
            'inventory' => self::isFeatureEnabled('inventory'),
            'downloads' => self::isFeatureEnabled('downloads'),
            'bookings' => self::isFeatureEnabled('bookings'),
            'subscriptions' => self::isFeatureEnabled('subscriptions'),
            'subscriptions' => self::isFeatureEnabled('subscriptions'),
            'bundles' => self::isFeatureEnabled('product_bundles'),
            'coupons' => self::isFeatureEnabled('coupons'),
            'tax' => self::isFeatureEnabled('tax'),
            'dropshipping' => self::isFeatureEnabled('dropshipping'),
        ];
    }
}
