<?php

namespace BitApps\PiPro\src\Integrations\FluentCart\Services;

use BitApps\Pi\Helpers\MixInputHandler;
use BitApps\Pi\src\Flow\NodeInfoProvider;
use BitApps\PiPro\src\Integrations\FluentCart\FluentCartHelper;
use FluentCart\App\Models\Product;
use FluentCart\App\Models\ProductDetail;
use FluentCart\App\Models\ProductVariation;

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

final class ProductService
{
    private $nodeInfoProvider;

    public function __construct(NodeInfoProvider $nodeInfoProvider)
    {
        $this->nodeInfoProvider = $nodeInfoProvider;
    }

    public function getAllProduct(): array
    {
        if ($validationResponse = FluentCartHelper::validateClassExistence('product')) {
            return $validationResponse;
        }

        $products = Product::all();
        $data = ['products' => FluentCartHelper::prepareData($products)];

        return [
            'response'    => $data,
            'payload'     => [],
            'status_code' => 200
        ];
    }

    public function getProductById(): array
    {
        $product = $this->validateAndGetProduct(['variants']);

        if (!$product instanceof Product) {
            return $product;
        }

        return [
            'response'    => FluentCartHelper::prepareData($product),
            'payload'     => [],
            'status_code' => 200
        ];
    }

    public function getProductVariants(): array
    {
        $product = $this->validateAndGetProduct();

        if (!$product instanceof Product) {
            return $product;
        }

        $data = [
            'variants' => FluentCartHelper::prepareData($product->variants ?? []),
        ];

        return [
            'response'    => $data,
            'payload'     => [],
            'status_code' => 200
        ];
    }

    public function createProduct(): array
    {
        if ($validationError = FluentCartHelper::validateClassExistence(['product', 'product_detail', 'product_variation'])) {
            return $validationError;
        }

        $fieldMappings = $this->getProductFieldMappings();

        $rules = [
            'post_title'   => ['required', 'sanitize:text'],
            'product_type' => ['required', 'sanitize:text'],
        ];

        if ($validationError = FluentCartHelper::validateFieldMap($fieldMappings, $rules)) {
            return $validationError;
        }

        $fieldMappings['post_name'] = sanitize_title($fieldMappings['post_name'] ?? $fieldMappings['post_title']);
        $fieldMappings['post_type'] = 'fluent_products';
        $fieldMappings['post_date'] = current_time('mysql');
        $fieldMappings['post_date_gmt'] = current_time('mysql', 1);

        $product = Product::create($fieldMappings);
        if (!$product) {
            return [
                'response'    => __('Failed to create the product.', 'bit-pi'),
                'payload'     => [],
                'status_code' => 500
            ];
        }

        FluentCartHelper::processGalleryImages($fieldMappings['gallery_image_ids'] ?? [], $product->ID);

        if (!empty($fieldMappings['featured_media_id'])) {
            set_post_thumbnail($product->ID, \intval($fieldMappings['featured_media_id']));
        }

        if (!empty($fieldMappings['product_categories'])) {
            $categories = FluentCartHelper::parseCommaSeparatedValues($fieldMappings['product_categories']);

            wp_set_post_terms($product->ID, $categories, 'product-categories');
        }

        if (!empty($fieldMappings['product_brands'])) {
            $brands = FluentCartHelper::parseCommaSeparatedValues($fieldMappings['product_brands']);

            wp_set_post_terms($product->ID, $brands, 'product-brands');
        }

        if (!empty($fieldMappings['product_price'])) {
            $price = \floatval($fieldMappings['product_price']) * 100;
            $manageStock = isset($fieldMappings['stock_quantity']) && \intval($fieldMappings['stock_quantity']) > 0 ? 1 : 0;
            $fulfillmentType = empty($fieldMappings['product_type']) ? 'physical' : $fieldMappings['product_type'];
            $manageDownloadable = $fulfillmentType === 'digital' && isset($fieldMappings['manage_downloadable']) && $fieldMappings['manage_downloadable'] ? 1 : 0;

            $otherInfo = [];

            if (!empty($fieldMappings['shipping_class'])) {
                $otherInfo['shipping_class'] = \intval($fieldMappings['shipping_class']);
            }

            ProductDetail::create(
                [
                    'post_id'             => $product->ID,
                    'min_price'           => $price,
                    'max_price'           => $price,
                    'manage_stock'        => $manageStock,
                    'fulfillment_type'    => $fulfillmentType,
                    'manage_downloadable' => $manageDownloadable,
                    'other_info'          => empty($otherInfo) ? null : $otherInfo,
                ]
            );

            $comparePrice = isset($fieldMappings['compare_price'])
                ? \floatval($fieldMappings['compare_price']) * 100
                : 0;

            $variationData = [
                'post_id'         => $product->ID,
                'variation_title' => 'Default',
                'item_price'      => $price,
                'compare_price'   => $comparePrice,
                'manage_stock'    => $manageStock,
                'stock_status'    => $fulfillmentType !== 'digital' && isset($fieldMappings['stock_status']) ? $fieldMappings['stock_status'] : 'in-stock'
            ];

            if ($fulfillmentType !== 'digital') {
                $variationData['total_stock'] = isset($fieldMappings['stock_quantity']) ? \intval($fieldMappings['stock_quantity']) : 0;
                $variationData['available'] = isset($fieldMappings['stock_quantity']) ? \intval($fieldMappings['stock_quantity']) : 0;
            }

            ProductVariation::create($variationData);
        }

        $product = $product->fresh();

        if ($product) {
            $product->load(['detail', 'variants']);
        }

        $data = FluentCartHelper::prepareData($product);

        return [
            'response'    => $data,
            'payload'     => $fieldMappings,
            'status_code' => 201
        ];
    }

    public function deleteProduct(): array
    {
        $product = $this->validateAndGetProduct();

        if (!$product instanceof Product) {
            return $product;
        }

        if (!$product->delete()) {
            return [
                'response'    => __('Failed to delete the product.', 'bit-pi'),
                'payload'     => [],
                'status_code' => 500
            ];
        }

        return [
            'response'    => __('Product deleted successfully.', 'bit-pi'),
            'payload'     => [],
            'status_code' => 200
        ];
    }

    /**
     * Validate and get Product.
     */
    private function validateAndGetProduct(array $relations = []): array|Product
    {
        if ($validationError = FluentCartHelper::validateClassExistence('product')) {
            return $validationError;
        }

        $fieldMappings = $this->nodeInfoProvider->getFieldMapData();
        $rules = ['id' => ['required', 'integer']];

        if ($validationError = FluentCartHelper::validateFieldMap($fieldMappings, $rules)) {
            return $validationError;
        }

        if (empty($relations)) {
            $product = Product::find($fieldMappings['id']);
        } else {
            $product = Product::with($relations)->find($fieldMappings['id']);
        }

        if (!$product) {
            return [
                'response'    => __('Product not found.', 'bit-pi'),
                'payload'     => [],
                'status_code' => 404
            ];
        }

        return $product;
    }

    /**
     * Get field mappings for product creation.
     */
    private function getProductFieldMappings(): array
    {
        $fieldMappings = $this->nodeInfoProvider->getFieldMapRepeaters('field-map.value', false, true, 'product_field');

        $mappings = [
            'product_type'        => 'product-type.value',
            'product_categories'  => 'product-categories.value',
            'product_brands'      => 'product-brands.value',
            'shipping_class'      => 'shipping-class.value',
            'manage_downloadable' => 'manage-downloadable.value',
            'featured_media_id'   => 'featured-media-id.value',
            'gallery_image_ids'   => 'gallery-image-ids.value',
        ];

        foreach ($mappings as $key => $configKey) {
            $fieldMappings[$key] = $this->nodeInfoProvider->getFieldMapConfigs($configKey);
        }

        $fieldMappings['featured_media_id'] = MixInputHandler::replaceMixTagValue($fieldMappings['featured_media_id']);
        $fieldMappings['gallery_image_ids'] = MixInputHandler::replaceMixTagValue($fieldMappings['gallery_image_ids']);

        return $fieldMappings;
    }
}
