<?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\Customer;

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

final class CustomerService
{
    private $nodeInfoProvider;

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

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

        $customers = Customer::all();
        $data = ['customers' => FluentCartHelper::prepareData($customers)];

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

    public function getCustomerById(): array
    {
        $customer = $this->validateAndGetCustomer(['orders']);

        if (!$customer instanceof Customer) {
            return $customer;
        }

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

    public function getCustomerOrders(): array
    {
        $customer = $this->validateAndGetCustomer(['orders']);

        if (!$customer instanceof Customer) {
            return $customer;
        }

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

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

    public function getCustomerSubscriptions(): array
    {
        $customer = $this->validateAndGetCustomer(['orders']);

        if (!$customer instanceof Customer) {
            return $customer;
        }

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

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

    public function getCustomerShippingAddress(): array
    {
        $customer = $this->validateAndGetCustomer(['orders']);

        if (!$customer instanceof Customer) {
            return $customer;
        }

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

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

    public function getCustomerBillingAddress(): array
    {
        $customer = $this->validateAndGetCustomer(['orders']);

        if (!$customer instanceof Customer) {
            return $customer;
        }

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

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

    public function getCustomerPrimaryShippingAddress(): array
    {
        $customer = $this->validateAndGetCustomer(['orders']);

        if (!$customer instanceof Customer) {
            return $customer;
        }

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

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

    public function getCustomerPrimaryBillingAddress(): array
    {
        $customer = $this->validateAndGetCustomer(['orders']);

        if (!$customer instanceof Customer) {
            return $customer;
        }

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

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

    public function getCustomerMetadata(): array
    {
        $customer = $this->validateAndGetCustomer(['orders']);

        if (!$customer instanceof Customer) {
            return $customer;
        }

        $data = [
            'metadata' => FluentCartHelper::prepareData($customer->customer_meta ?? []),
        ];

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

    public function getCustomerLabels(): array
    {
        $customer = $this->validateAndGetCustomer(['orders']);

        if (!$customer instanceof Customer) {
            return $customer;
        }

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

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

    public function createCustomer(): array
    {
        if ($validationError = FluentCartHelper::validateClassExistence('customer')) {
            return $validationError;
        }

        $fieldMappings = $this->nodeInfoProvider->getFieldMapRepeaters('field-map.value', false, true, 'customer_field');
        $rules = ['email' => ['required', 'sanitize:email']];

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

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

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

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

    public function updateCustomer(): array
    {
        if ($validationError = FluentCartHelper::validateClassExistence('customer')) {
            return $validationError;
        }

        $customerIdConfig = $this->nodeInfoProvider->getFieldMapConfigs('customer-id.value');
        $fieldMappings = $this->nodeInfoProvider->getFieldMapRepeaters('field-map.value', false, true, 'customer_field');

        $fieldMappings['customer_id'] = MixInputHandler::replaceMixTagValue($customerIdConfig);
        $rules = ['customer_id' => ['required', 'integer']];

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

        $customer = Customer::find($fieldMappings['customer_id']);
        if (!$customer) {
            return [
                'response'    => __('Customer not found.', 'bit-pi'),
                'payload'     => [],
                'status_code' => 404
            ];
        }

        unset($fieldMappings['customer_id']);
        $customer->update($fieldMappings);

        $data = FluentCartHelper::prepareData($customer->fresh());

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

    public function deleteCustomer(): array
    {
        $customer = $this->validateAndGetCustomer(['orders']);

        if (!$customer instanceof Customer) {
            return $customer;
        }

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

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

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

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

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

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

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

        return $customer;
    }
}
