<?php

namespace StevenBuehner\sbChurchtoolsGrouphomepage\Service\Models;

class PersonData {

	protected int $id;

	protected string $firstName   = '';
	protected string $lastName    = '';
	protected string $email       = '';
	protected string $phone       = '';
	protected string $iconUrl     = '';
	protected array  $groupValues = [];

	const GROUP_NAME = '_g';

	const GROUP_ROLE = '_r';
	const FIRSTNAME  = 'firstname';
	const LASTNAME   = 'lastname';
	const FULLNAME   = 'fullname';
	const EMAIL      = 'email';
	const PHONE      = 'phone';
	const ICON       = 'icon';
	const GENDER     = 'gender';

	public function __construct(int $id, string $firstName, string $lastName) {
		$this->setId($id);
		$this->setFirstName($firstName);
		$this->setLastName($lastName);
	}


	public function getId(): int {
		return $this->id;
	}

	public function setId(int $id): void {
		$this->id = $id;
	}

	public function getFirstName(): string {
		return $this->firstName;
	}

	public function setFirstName(string $firstName): void {
		$this->firstName = $firstName;
	}

	public function getLastName(): string {
		return $this->lastName;
	}

	public function setLastName(string $lastName): void {
		$this->lastName = $lastName;
	}

	public function getFullName(): string {
		return trim($this->getFirstName() . ' ' . $this->getLastName());
	}

	public function getEmail(): string {
		return $this->email;
	}

	public function setEmail(string $email): void {
		$this->email = $email;
	}

	public function getPhone(): string {
		return $this->phone;
	}

	public function setPhone(string $phone): void {
		$this->phone = $phone;
	}

	public function getIconUrl(): string {
		return $this->iconUrl;
	}

	public function setIconUrl(string $iconUrl): void {
		$this->iconUrl = $iconUrl;
	}


	protected function addGroupIfNotExisting(int $groupId) {
		if (!isset($this->groupValues[$groupId])) {
			$this->groupValues[$groupId] = [];
		}
	}

	public function addGroupName(int $groupId, string $groupName): void {
		$this->addGroupField($groupId, self::GROUP_NAME, $groupName);
	}


	public function addGroupField(int $groupId, string $fieldName, string $fieldValue): void {
		$this->addGroupIfNotExisting($groupId);
		$this->groupValues[$groupId][$fieldName] = $fieldValue;
	}

	public function getGroupField(int $groupId, string $fieldName, $defaultValue = NULL): mixed {
		if (isset($this->groupValues[$groupId][$fieldName])) {
			return $this->groupValues[$groupId][$fieldName];
		} else {
			return $defaultValue;
		}
	}

	public function getGroupValues(): array {
		return $this->groupValues;
	}

	public function setGroupValues(array $groupValues): void {
		$this->groupValues = $groupValues;
	}

	/**
	 *  Gibt nur die in $pops übergebenen Keys aller Personen als Array zurück.
	 * Besonderheit sind Gruppenfelder. Diese können angefordert werden (sofern sie zuvor eingepflegt wurden) nach dem System
	 * ID:Feldname (z.B. "8:_groupname")
	 *
	 * @param array $props An array of property keys to be serialized. Keys can include:
	 * - `FIRSTNAME`: Retrieves the first name.
	 * - `LASTNAME`: Retrieves the last name.
	 * - `FULLNAME`: Retrieves the full name (combination of first and last name).
	 * - `EMAIL`: Retrieves the email address.
	 * - `PHONE`: Retrieves the phone number.
	 * - `ICON`: Retrieves the URL of the user's icon.
	 * - Custom group fields in the format `{id}:{fieldname}`, where:
	 * - `{id}` is a numeric group identifier.
	 * - `{fieldname}` is the name of the field within the group.
	 * @return array<string, mixed> An associative array containing the serialized data. The structure includes:
	 * - `groupValues`: An array initialized as empty, reserved for additional grouped data.
	 * - Keys matching `$props`:
	 * - `FIRSTNAME` => string|null: The user's first name.
	 * - `LASTNAME` => string|null: The user's last name.
	 * - `FULLNAME` => string|null: The user's full name.
	 * - `EMAIL` => string|null: The user's email address.
	 * - `PHONE` => string|null: The user's phone number.
	 * - `ICON` => string|null: The URL of the user's icon.
	 * - For custom group fields (`{id}:{fieldname}`):
	 * - `{id}:{fieldname}` => mixed: The value of the specified group field, as returned by `getGroupField()`.
	 */
	public function serializeOnly(array &$props): array {

		$response    = [
			'groupValues' => []
		];
		$groupValues = [];

		foreach ($props as $propValue) {
			switch ($propValue) {
				case self::FIRSTNAME:
					$response[self::FIRSTNAME] = $this->getFirstName();
					break;
				case self::LASTNAME:
					$response[self::LASTNAME] = $this->getLastName();
					break;
				case self::FULLNAME:
					$response[self::FULLNAME] = $this->getFullName();
					break;
				case self::EMAIL:
					$response[self::EMAIL] = $this->getEmail();
					break;
				case self::PHONE:
					$response[self::PHONE] = $this->getPhone();
					break;
				case self::ICON:
					$response[self::ICON] = $this->getIconUrl();
					break;
				default:
					if (preg_match('~(?<id>[0-9]+):(?<fieldname>[0-9a-zA-Z_ -]+)~', $propValue, $matches) === 1) {

						$id        = (int)$matches['id'];
						$fieldname = $matches['fieldname'];
						$value     = $this->getGroupField($id, $fieldname, NULL);

						// Füge den Wert nur dann zum Rückgabeergebnis hinzu, wenn er auch befüllt worden ist (= nicht NULL ist)
						if (!empty($value)) {

							if (!isset($groupValues[$id])) {
								$groupValues[$id] = [];
							}

							$groupValues[$id][$fieldname] = $value;

						}

					}
			}
		}

		// am Ende die GroupValues anonymisieren, so dass auch die Gruppen IDs nicht mehr erkennbar sind
		foreach ($groupValues as $val) {
			$response['groupValues'][] = $val;
		}

		return $response;
	}

	public function serializeAll() {
		return [
			self::FIRSTNAME => $this->getFirstName(),
			self::LASTNAME  => $this->getLastName(),
			self::FULLNAME  => $this->getFullName(),
			self::EMAIL     => $this->getEmail(),
			self::PHONE     => $this->getPhone(),
			self::ICON      => $this->getIconUrl(),
			'groupValues'   => $this->getGroupValues()
		];
	}

}
