<?php

namespace ShopManagerPro\ACF;

use ShopManagerPro\ACF\DTO\ACFField;
use ShopManagerPro\ACF\DTO\ACFFieldGroup;
use ShopManagerPro\ACF\DTO\ACFFieldType;

class ACFRepository {
	private static ?DTO\ACFCollection $acfFields = null;

	public static function setTestACFFields(?DTO\ACFCollection $fields = null) {
		self::$acfFields = $fields;
	}

	public static function getACFFields() {
		if (self::$acfFields) {
			return self::$acfFields;
		} global $wpdb;
		$query = "
            SELECT
                wp_posts.id ,
                wp_posts.post_title ,
				wp_posts.post_name ,
                wp_posts.post_excerpt ,
                wp_posts.post_content ,
                wp_posts.post_type ,
                wp_posts.post_parent
            FROM
                {$wpdb->posts} AS wp_posts
            WHERE
                wp_posts.post_type IN ('acf-field-group' , 'acf-field') AND
				wp_posts.post_status = 'publish'
            ";
		$acfFieldGroups = [];
		foreach ($wpdb->get_results($query, ARRAY_A) as $row) {
			$id = intval($row['id']);
			$parentId = intval($row['post_parent']);
			if ($row['post_type'] === 'acf-field-group') {
				self::createOrUpdateFieldGroup($acfFieldGroups, $row);
			} elseif ('acf-field' === $row['post_type']) {
				$acfField = self::getACFFieldByRow($row);
				if (!$acfField->editable) {
					continue;
				} if (!isset($acfFieldGroups[$parentId])) {
					$acfFieldGroups[$parentId] = new ACFFieldGroup(id: $parentId, name: '', fields: []);
				} $acfFieldGroups[$parentId]->fields[$id] = $acfField;
			} else {
				throw new \Exception('Unexpected post type: '.$row->post_type);
			}
		} $acfFieldGroups = array_filter($acfFieldGroups, function ($group) { return !empty($group->fields) && !empty($group->name); });
		$acfFieldsByID = [];
		$acfFieldsByKey = [];
		$acfFieldsByName = [];
		foreach ($acfFieldGroups as $group) {
			foreach ($group->fields as $field) {
				$acfFieldsByID[$field->id] = $field;
				$acfFieldsByKey[$field->key] = $field;
				$acfFieldsByName[$field->name] = $field;
			}
		} self::$acfFields = new DTO\ACFCollection(acfFieldGroups: $acfFieldGroups, acfFieldsByKey: $acfFieldsByKey, acfFieldsById : $acfFieldsByID, acfFieldsByName: $acfFieldsByName);

		return self::$acfFields;
	}

	public static function clearCache() {
		self::$acfFields = null;
	}

	public static function convertByIDtoByKey(array $acfFields) {
		$allAcfFields = self::getACFFields();
		$acfFieldsByKey = [];
		foreach ($acfFields as $id => $acfField) {
			$id = intval($id);
			if (isset($allAcfFields->acfFieldsById[$id])) {
				$acfFieldsByKey[$allAcfFields->acfFieldsById[$id]->key] = $acfField;
			} else {
				throw new \Exception('ACF field not found by ID: '.$id);
			}
		}

return $acfFieldsByKey;
	}

	private static function isFieldGroupActiveForProductPostType(array $row) {
		$fieldGroupData = unserialize($row['post_content']);
		if (isset($fieldGroupData['active']) && !$fieldGroupData['active']) {
			return false;
		} if (!isset($fieldGroupData['location']) || !is_array($fieldGroupData['location'])) {
			return false;
		} foreach ($fieldGroupData['location'] as $ruleGroup) {
			if (!is_array($ruleGroup)) {
				continue;
			} $matchesProduct = false;
			foreach ($ruleGroup as $rule) {
				if (!is_array($rule)) {
					continue;
				} if (isset($rule['param']) && $rule['param'] === 'post_type' && isset($rule['operator']) && $rule['operator'] === '==' && isset($rule['value']) && $rule['value'] === 'product') {
					$matchesProduct = true;
					break;
				}
			} if ($matchesProduct) {
				return true;
			}
		}

return false;
	}

	private static function createOrUpdateFieldGroup(array &$acfFieldGroups, array $row) {
		$id = intval($row['id']);
		if (intval($row['post_parent'])) {
			throw new \Exception("ACF field groups should not have parent. Unexpected post parent for $id: ".$row['post_parent']);
		} if (!self::isFieldGroupActiveForProductPostType($row)) {
			return;
		} if (isset($acfFieldGroups[$id])) {
			$acfFieldGroups[$id]->name = $row['post_title'];
		} else {
			$acfFieldGroups[$id] = new ACFFieldGroup(id: $id, name: $row['post_title'], fields: []);
		}
	}

	private static function getACFFieldByRow(array $row) {
		$fieldProperties = unserialize($row['post_content']);
		$type = $fieldProperties['type'] ?? 'text';
		$editable = false;
		if (is_string($type)) {
			$supportedTypes = array_column(ACFFieldType::cases(), 'value');
			$editable = in_array($type, $supportedTypes, true);
		}

return new ACFField(id: intval($row['id']), type: $type, key: $row['post_name'], editable: $editable, label: $row['post_title'], name: $row['post_excerpt'], multiple: ($fieldProperties['multiple'] ?? false) || $type === 'checkbox', choices: self::fieldPropertiesToChoices($fieldProperties));
	}

	private static function fieldPropertiesToChoices(array $fieldProperties) {
		if (isset($fieldProperties['choices']) && is_array($fieldProperties['choices'])) {
			return $fieldProperties['choices'];
		}

return null;
	}
}
