<?php

namespace Easymailing\App\Controller\Admin;

use Easymailing\App\Model\Config;
use Easymailing\App\Core\Http\Request;

class SettingsController extends BaseSynchronizationController
{
    public function indexAction(): void
    {
        $this->checkConfig();
        $this->checkGeneralData();
		$request = $this->getRequest();

        try {
            // Retrieve external data
            [$treatmentPurposes, $booleanListFields] = $this->fetchExternalData();

        } catch (\Exception $e) {
            $this->renderError("An error occurred: " . $e->getMessage());
            return;
        }

        // If the request is GET, render the view with the retrieved data
        if ($request->getMethod() === Request::METHOD_GET) {
            $this->renderView($treatmentPurposes, $booleanListFields);
            return;
        }

        // If the request is POST, process the form
        if ($request->getMethod() === Request::METHOD_POST) {
            $this->processPostRequest($treatmentPurposes, $booleanListFields);
			$this->updateAudienceInConfig();
			$this->redirectAfterSavedData();
        }
    }


    /**
     * Fetches the audience and fields from the external API.
     */
    private function fetchExternalData(): array
    {

		$synchronizationConfig = $this->getSynchronizationConfig();
        $audience = $this->getApiClient()->getAudienceById($synchronizationConfig->getAudience());
        $listFields = $this->getAudienceFromSynchronizationConfig()->listFields;

	    $treatmentPurposes = [];

		if($audience->listGdpr->enabled){
			$treatmentPurposes = $this->mapTreatmentPurposes($audience->listGdpr->treatmentPurposes, $synchronizationConfig->getLanguage());
		}

        $booleanListFields = $this->mapListFields($listFields, $synchronizationConfig->getLanguage());

        $this->addStatusToTreatmentPurposes($treatmentPurposes, $synchronizationConfig->getTreatmentPurposes());
        $this->addStatusToTreatmentPurposes($booleanListFields, $synchronizationConfig->getBooleanListFields());

        return [$treatmentPurposes, $booleanListFields];
    }

	private function updateAudienceInConfig(): void
	{
		$repository = $this->getContainer()->get('config_repository');
		$synchronizationConfig = $this->getSynchronizationConfig();
	    $audience = $this->getApiClient()->getAudienceArrayById($synchronizationConfig->getAudience());
	    $synchronizationConfig->setAudienceJson(json_encode($audience));
	    $repository->saveSynchronizationConfig($synchronizationConfig);

	}

    /**
     * Maps treatment purposes.
     */
    private function mapTreatmentPurposes($treatmentPurposes, string $locale): array
    {
        return array_map(function ($item) use ($locale) {
			$translation = $this->getTranslation($item->translations, $locale);

            return [
                'id' => $item->id,
                'title' => $translation->title,
            ];
        }, $treatmentPurposes);
    }

    /**
     * Maps list fields.
     */
    private function mapListFields($listFields, string $locale): array
    {
		$result = array_filter($listFields, function ($item) {
			return $item->type === "list.field.type.boolean";
		});


	    return array_map(function ($item) use ($locale) {
	        $translation = $this->getTranslation($item->translations, $locale);
            return [
                'id' => $item->id,
                'title' => $translation->label,
            ];
        }, $result);

    }

    /**
     * Processes the POST request and saves the configuration.
     */
    private function processPostRequest($treatmentPurposes, $booleanListFields): void
    {

	    $request = $this->getRequest();
	    $synchronizationConfig = $this->getSynchronizationConfig();
	    $repository = $this->getContainer()->get('config_repository');

        // Filter the request to get only treatment checks
        $result = array_filter($request->request->all(), function ($key) {
            return strpos($key, 'emcheck') === 0;
        }, ARRAY_FILTER_USE_KEY);

        $counter = 0;

        // Save treatment purposes
        $this->saveConfigData($treatmentPurposes, $result, 'setTreatmentPurposes', $synchronizationConfig, $counter);

        // Save list fields
        $this->saveConfigData($booleanListFields, $result, 'setBooleanListFields', $synchronizationConfig, $counter);

        // Save the configuration in the repository
        $repository->saveSynchronizationConfig($synchronizationConfig);

        // Update the status for treatment purposes and list fields
        $this->addStatusToTreatmentPurposes($treatmentPurposes, $synchronizationConfig->getTreatmentPurposes());
        $this->addStatusToTreatmentPurposes($booleanListFields, $synchronizationConfig->getBooleanListFields());

	    $this->getFlashBag()->add('success', __('La configuración se ha guardado correctamente','easymailing'));

    }

	protected function redirectAfterSavedData()
	{
		$this->redirectToMenuPage('easymailing_synchronization_settings');
	}

    /**
     * Adds status to treatment purposes based on the configuration.
     */
    private function addStatusToTreatmentPurposes(&$treatmentPurposes, $configTreatmentPurposes): void
    {
        foreach ($treatmentPurposes as &$item) {
	        $item['status'] = "hidden";

            // Check if the ID exists in configTreatmentPurposes and set the corresponding status
            if (isset($item['id']) and is_array($configTreatmentPurposes)) {
	            $item['status'] = $configTreatmentPurposes[$item['id']];
            }
        }
    }

    /**
     * Filters translations based on locale preferences.
     */
	private function getTranslation(array $translations, $locale)
	{
		foreach ($translations as $t) {
			if ($t->locale === $locale) {
				return $t;
			}
		}
		throw new \Exception("No translation found for locale: $locale");
	}

    /**
     * Saves configuration data by mapping the results to the corresponding fields.
     */
    private function saveConfigData($fields, $result, $setterMethod, $config, &$counter)
    {
        $data = [];
        foreach ($fields as $value) {
            if (isset(array_values($result)[$counter])) {
                $data[$value['id']] = array_values($result)[$counter];
            }
            $counter++;
        }
        $config->$setterMethod($data);
    }

    /**
     * Renders the view with provided configuration and data.
     */
    protected function renderView($treatmentPurposes, $booleanListFields)
    {
        $data = (count($treatmentPurposes) > 0) ? $treatmentPurposes : $booleanListFields;
        $this->render('Admin/Synchronization/settings.php', [
            'current_page' => 2,
            'treatmentPurposes' => $data,
        ]);
    }

    /**
     * Renders an error message.
     */
    private function renderError($message)
    {
        $this->render('Admin/Synchronization/error.php', [
            'message' => $message,
            'current_page' => 2,
        ]);
    }
}
