<?php

namespace BitApps\PiPro\src\Integrations\MailPoet;

use BitApps\Pi\Deps\BitApps\WPValidator\Validator;
use BitApps\Pi\src\Flow\NodeInfoProvider;
use Exception;
use MailPoet\API\API;

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


final class MailPoetServices
{
    private $nodeInfoProvider;

    private $mailPoetApi;

    public function __construct(NodeInfoProvider $nodeInfoProvider)
    {
        $this->nodeInfoProvider = $nodeInfoProvider;
        $this->mailPoetApi = API::MP('v1');
    }

    /**
     * Create List.
     *
     * @return collection
     */
    public function createList()
    {
        $fieldMappings = $this->nodeInfoProvider->getFieldMapData();

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

        $validationErrors = self::validateFieldMap($fieldMappings, $rules);

        if (!empty($validationErrors)) {
            return $validationErrors;
        }

        try {
            return [
                'response'    => $this->mailPoetApi->addList($fieldMappings),
                'payload'     => $fieldMappings,
                'status_code' => 200
            ];
        } catch (Exception $e) {
            return [
                'response'    => $e->getMessage(),
                'payload'     => $fieldMappings,
                'status_code' => 400
            ];
        }
    }

    /**
     * Update List.
     *
     * @return collection
     */
    public function updateList()
    {
        $fieldMappings = $this->nodeInfoProvider->getFieldMapData();

        $rules = [
            'id'   => ['required', 'integer'],
            'name' => ['required', 'sanitize:text'],
        ];

        $validationErrors = self::validateFieldMap($fieldMappings, $rules);

        if (!empty($validationErrors)) {
            return $validationErrors;
        }

        try {
            return [
                'response'    => $this->mailPoetApi->updateList($fieldMappings),
                'payload'     => $fieldMappings,
                'status_code' => 200
            ];
        } catch (Exception $e) {
            return [
                'response'    => $e->getMessage(),
                'payload'     => $fieldMappings,
                'status_code' => 400
            ];
        }
    }

    /**
     * Delete List.
     *
     * @return collection
     */
    public function deleteList()
    {
        $fieldMappings = $this->nodeInfoProvider->getFieldMapData();

        $rules = [
            'id' => ['required', 'integer']
        ];

        $validationErrors = self::validateFieldMap($fieldMappings, $rules);

        if (!empty($validationErrors)) {
            return $validationErrors;
        }

        try {
            return [
                'response'    => $this->mailPoetApi->deleteList($fieldMappings['id']),
                'payload'     => $fieldMappings,
                'status_code' => 200
            ];
        } catch (Exception $e) {
            return [
                'response'    => $e->getMessage(),
                'payload'     => $fieldMappings,
                'status_code' => 400
            ];
        }
    }

    /**
     * Get all lists.
     *
     * @return collection
     */
    public function getAllList()
    {
        try {
            return [
                'response'    => $this->mailPoetApi->getLists(),
                'payload'     => [],
                'status_code' => 200
            ];
        } catch (Exception $e) {
            return [
                'response'    => $e->getMessage(),
                'payload'     => [],
                'status_code' => 400
            ];
        }
    }

    /**
     * Create Subscriber.
     *
     * @return collection
     */
    public function createSubscriber()
    {
        $fieldMappings = $this->nodeInfoProvider->getFieldMapData();
        $fieldMappings['field_map'] = $this->nodeInfoProvider->getFieldMapRepeaters('field-map.value', false, true, 'mailPoetField', 'value');

        $rules = [
            'field_map.email' => ['required', 'email']
        ];

        $validationErrors = self::validateFieldMap($fieldMappings, $rules);

        if (!empty($validationErrors)) {
            return $validationErrors;
        }

        try {
            $result = $this->mailPoetApi->addSubscriber(
                $fieldMappings['field_map'],
                $fieldMappings['list_ids'] ?? [],
                $fieldMappings['options'] ?? []
            );

            return [
                'response'    => $result,
                'payload'     => $fieldMappings,
                'status_code' => 200
            ];
        } catch (Exception $e) {
            return [
                'response'    => $e->getMessage(),
                'payload'     => $fieldMappings,
                'status_code' => 400
            ];
        }
    }

    /**
     * Update Subscriber.
     *
     * @return collection
     */
    public function updateSubscriber()
    {
        $fieldMappings = $this->nodeInfoProvider->getFieldMapRepeaters('field-map.value', false, true, 'mailPoetField', 'value');

        $rules = [
            'email' => ['required', 'email']
        ];

        $validationErrors = self::validateFieldMap($fieldMappings, $rules);

        if (!empty($validationErrors)) {
            return $validationErrors;
        }

        try {
            $result = $this->mailPoetApi->updateSubscriber(
                $fieldMappings['email'],
                $fieldMappings
            );

            return [
                'response'    => $result,
                'payload'     => $fieldMappings,
                'status_code' => 200
            ];
        } catch (Exception $e) {
            return [
                'response'    => $e->getMessage(),
                'payload'     => $fieldMappings,
                'status_code' => 400
            ];
        }
    }

    /**
     * Get Subscriber by ID.
     *
     * @return collection
     */
    public function getSubscriber()
    {
        $fieldMappings = $this->nodeInfoProvider->getFieldMapData();

        $rules = [
            'id' => ['required', 'integer']
        ];

        $validationErrors = self::validateFieldMap($fieldMappings, $rules);

        if (!empty($validationErrors)) {
            return $validationErrors;
        }

        try {
            return [
                'response'    => $this->mailPoetApi->getSubscriber($fieldMappings['id']),
                'payload'     => $fieldMappings,
                'status_code' => 200
            ];
        } catch (Exception $e) {
            return [
                'response'    => $e->getMessage(),
                'payload'     => $fieldMappings,
                'status_code' => 400
            ];
        }
    }

    /**
     * Get Subscriber by List ID.
     *
     * @return collection
     */
    public function getSubscriberByList()
    {
        $fieldMappings = $this->nodeInfoProvider->getFieldMapData();

        $rules = [
            'id' => ['required', 'integer']
        ];

        $validationErrors = self::validateFieldMap($fieldMappings, $rules);

        if (!empty($validationErrors)) {
            return $validationErrors;
        }

        return $this->getSubscribers(
            [
                'listId' => $fieldMappings['id']
            ]
        );
    }

    /**
     * Get Subscriber by Status.
     *
     * @return collection
     */
    public function getSubscriberByStatus()
    {
        $fieldMappings = $this->nodeInfoProvider->getFieldMapData();

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

        $validationErrors = self::validateFieldMap($fieldMappings, $rules);

        if (!empty($validationErrors)) {
            return $validationErrors;
        }

        return $this->getSubscribers($fieldMappings);
    }

    /**
     * Get Subscriber Count.
     *
     * @return collection
     */
    public function getSubscriberCount()
    {
        $fieldMappings = $this->nodeInfoProvider->getFieldMapData();
        $filter = [];

        if (isset($fieldMappings['status'])) {
            $filter['status'] = $fieldMappings['status'];
        }

        if (isset($fieldMappings['list_id'])) {
            $filter['listId'] = $fieldMappings['list_id'];
        }

        try {
            $count = $this->mailPoetApi->getSubscribersCount($filter);

            return [
                'response'    => $count,
                'payload'     => $fieldMappings,
                'status_code' => 200
            ];
        } catch (Exception $e) {
            return [
                'response'    => $e->getMessage(),
                'payload'     => $fieldMappings,
                'status_code' => 400
            ];
        }
    }

    /**
     * Subscribe to Lists.
     *
     * @return collection
     */
    public function subscribeToLists()
    {
        $fieldMappings = $this->nodeInfoProvider->getFieldMapData();

        $rules = [
            'subscriber_id' => ['required', 'integer'],
            'list_ids'      => ['required', 'array']
        ];

        $validationErrors = self::validateFieldMap($fieldMappings, $rules);

        if (!empty($validationErrors)) {
            return $validationErrors;
        }

        try {
            $result = $this->mailPoetApi->subscribeToLists(
                $fieldMappings['subscriber_id'],
                $fieldMappings['list_ids'],
                $fieldMappings['options'] ?? []
            );

            return [
                'response'    => $result,
                'payload'     => $fieldMappings,
                'status_code' => 200
            ];
        } catch (Exception $e) {
            return [
                'response'    => $e->getMessage(),
                'payload'     => $fieldMappings,
                'status_code' => 400
            ];
        }
    }

    /**
     * Unsubscribe Globally.
     *
     * @return collection
     */
    public function unsubscribeGlobally()
    {
        $fieldMappings = $this->nodeInfoProvider->getFieldMapData();

        $rules = [
            'id' => ['required', 'integer']
        ];

        $validationErrors = self::validateFieldMap($fieldMappings, $rules);

        if (!empty($validationErrors)) {
            return $validationErrors;
        }

        try {
            return [
                'response'    => $this->mailPoetApi->unsubscribe($fieldMappings['id']),
                'payload'     => $fieldMappings,
                'status_code' => 200
            ];
        } catch (Exception $e) {
            return [
                'response'    => $e->getMessage(),
                'payload'     => $fieldMappings,
                'status_code' => 400
            ];
        }
    }

    /**
     * Unsubscribe from Lists.
     *
     * @return collection
     */
    public function unsubscribeFromLists()
    {
        $fieldMappings = $this->nodeInfoProvider->getFieldMapData();

        $rules = [
            'subscriber_id' => ['required', 'integer'],
            'list_ids'      => ['required', 'array']
        ];

        $validationErrors = self::validateFieldMap($fieldMappings, $rules);

        if (!empty($validationErrors)) {
            return $validationErrors;
        }

        try {
            $result = $this->mailPoetApi->unsubscribeFromLists(
                $fieldMappings['subscriber_id'],
                $fieldMappings['list_ids']
            );

            return [
                'response'    => $result,
                'payload'     => $fieldMappings,
                'status_code' => 200
            ];
        } catch (Exception $e) {
            return [
                'response'    => $e->getMessage(),
                'payload'     => $fieldMappings,
                'status_code' => 400
            ];
        }
    }

    public function getSubscribers($fieldMappings = [])
    {
        $args = [];

        if (isset($fieldMappings['listId'])) {
            $args['listId'] = (int) $fieldMappings['listId'];
        }

        if (isset($fieldMappings['status'])) {
            $args['status'] = $fieldMappings['status'];
        }

        try {
            return [
                'response'    => $this->mailPoetApi->getSubscribers($args, 1000),
                'payload'     => $fieldMappings,
                'status_code' => 200
            ];
        } catch (Exception $e) {
            return [
                'response'    => $e->getMessage(),
                'payload'     => $fieldMappings,
                'status_code' => 400
            ];
        }
    }

    private static function validateFieldMap($fieldMappings, $validationRules, $payload = null)
    {
        $validator = new Validator();
        $validation = $validator->make($fieldMappings, $validationRules);

        if ($validation->fails()) {
            return [
                'response'    => $validation->errors(),
                'payload'     => $payload ?? $fieldMappings,
                'status_code' => 400
            ];
        }
    }
}
