<?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');
    }

    /**
     * Whether a feature is available. Tier-driven since the addons layer was
     * collapsed (2026-07-29): no live site ever activated an addon, so the
     * per-addon config checks all returned false and only hid features the
     * product already ships. Booking/subscription surfaces follow the STORE
     * TYPE (they exist because of what the store is, not what it pays);
     * everything else is simply part of the product on any paid/full install
     * and absent on the free tier, which is render-gated by TierManager as
     * everywhere else.
     */
    public static function isFeatureEnabled(string $feature): bool
    {
        switch ($feature) {
            case 'bookings':
                return in_array(self::getStoreType(), ['services', 'salon', 'home_services', 'restaurant', 'automotive', 'instructor', 'mixed'], true);
            case 'subscriptions':
                return in_array(self::getStoreType(), ['subscriptions', 'memberships', 'mixed'], true);
            case 'shipping':
            case 'inventory':
                return self::hasPhysicalProducts();
            case 'downloads':
                return self::hasDigitalProducts();
            default:
                return \Instinctor\Core\TierManager::isDevMode() || \Instinctor\Core\TierManager::isPro();
        }
    }

    /**
     * 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;
    }

            }
