<?php

use Contao\Backend;
use Contao\BackendUser;
use Contao\DC_Table;
use Contao\System;
use Contao\CoreBundle\Security\ContaoCorePermissions;
use Contao\StringUtil;
use Contao\Image;
use CreoCode\ContaoFormSubmissions\Model\FormSubmissionsSetModel;
use CreoCode\ContaoFormSubmissions\Model\FormSubmissionsDataModel;


/**
 * Table tl_form_submissions
 */
$GLOBALS['TL_DCA']['tl_form_submissions'] = array
    (
    // Config
    'config' => array
        (
        'dataContainer' => DC_Table::class,
        'ptable' => 'tl_form_submissions_set',
        'closed' => true,
        'notEditable' => true,
        'ondelete_callback' => array(array('tl_form_submissions', 'deleteSubmission')),
        'sql' => array
            (
            'keys' => array
                (
                'id' => 'primary',
                'pid' => 'index'
            )
        )
    ),
    // List
    'list' => array
        (
        'sorting' => array
            (
            'mode' => 2,
            'fields' => array('tstamp DESC'),
            'panelLayout' => 'search,limit'
        ),
        'label' => array
            (
            'fields' => array('tstamp'),
            'label_callback' => array('tl_form_submissions', 'generateLabel'),
            'group_callback' => array('tl_form_submissions', 'groupCallback'),
            'maxCharacters' => 96
        ),
        'global_operations' => array
            (
            'all' => array
                (
                'label' => &$GLOBALS['TL_LANG']['MSC']['all'],
                'href' => 'act=select',
                'class' => 'header_edit_all',
                'attributes' => 'onclick="Backend.getScrollOffset()" accesskey="e"'
            )
        ),
        'operations' => array
            (
            'showForm' => array
                (
                'label' => &$GLOBALS['TL_LANG']['tl_form_submissions']['showForm'],
                'icon' => 'show.gif',
                'button_callback' => array('tl_form_submissions', 'showForm')
            ),
            'resendForm' => array
                (
                'label' => &$GLOBALS['TL_LANG']['tl_form_submissions']['resendForm'],
                'icon' => 'bundles/contaoformsubmissions/img/backend/icons/paper-plane.svg',
                'button_callback' => array('tl_form_submissions', 'resendForm')
            ),
            'delete' => array
                (
                'label' => &$GLOBALS['TL_LANG']['tl_form_submissions']['delete'],
                'href' => 'act=delete',
                'icon' => 'delete.gif',
                'attributes' => 'onclick="if(!confirm(\'' . ($GLOBALS['TL_LANG']['MSC']['deleteConfirm'] ?? null) . '\'))return false;Backend.getScrollOffset()"'
            )
        )
    ),
    // Palettes
    'palettes' => array
        (
        'default' => '{data_legend},data;'
    ),
    // Fields
    'fields' => array
        (
        'id' => array
            (
            'sql' => "int(10) unsigned NOT NULL auto_increment"
        ),
        'pid' => array
            (
            'label' => &$GLOBALS['TL_LANG']['tl_form_submissions']['pid'],
            'foreignKey' => 'tl_form_submissions_set.form_title',
            'sql' => "int(10) unsigned NOT NULL default '0'",
            'relation' => array('type' => 'belongsTo', 'load' => 'eager')
        ),
        'form_id' => array
            (
            'label' => &$GLOBALS['TL_LANG']['tl_form_submissions']['form_id'],
            'foreignKey' => 'tl_form.id',
            'sql' => "int(10) unsigned NOT NULL default '0'",
            'relation' => array('type' => 'belongsTo')
        ),
        'tstamp' => array
            (
            'label' => &$GLOBALS['TL_LANG']['tl_form_submissions']['tstamp'],
            'filter' => true,
            'sorting' => true,
            'flag' => 6,
            'sql' => "int(10) unsigned NOT NULL default '0'"
        ),
        'recipient' => array
            (
            'label' => &$GLOBALS['TL_LANG']['tl_form_submissions']['recipient'],
            'filter' => true,
            'search' => true,
            'sql' => "varchar(1024) NOT NULL default ''"
        )
    )
);

/**
 * Class tl_form_submissions
 */
class tl_form_submissions extends Backend {

	/**
	 * Import the back end user object
	 */
	public function __construct()
	{
		parent::__construct();
		$this->import(BackendUser::class, 'User');
	}

	/**
	 * Loest {{field_value::...}}-InsertTags im Anzeigemuster auf.
	 *
	 * Syntax (analog zu Contao-InsertTags: :: = Parameter, | = Flags):
	 *   {{field_value::feldname}}
	 *   {{field_value::feldname::fallback_text}}
	 *   {{field_value::feld1::feld2::fallback_text}}
	 *
	 * Alle ::-getrennten Teile werden der Reihe nach als Feldname geprueft.
	 * Der erste Teil mit einem nicht-leeren Wert wird verwendet.
	 * Liefert kein Teil einen Treffer, wird der letzte Teil als
	 * literaler Fallback-Text angezeigt.
	 *
	 * Contao-Flags (|flag) werden ignoriert.
	 *
	 * Beispiele:
	 *   {{field_value::name}}
	 *   {{field_value::email::kontakt_email::E-Mail unbekannt}}
	 *   {{field_value::firstname}} {{field_value::lastname}}
	 *   {{field_value::subject::Kein Betreff}}
	 */
	private function resolvePattern(string $pattern, array $arrSubmitted): string
	{
		return preg_replace_callback(
			'/\{\{field_value::([^|}]+)(?:\|[^}]*)?\}\}/',
			static function (array $matches) use ($arrSubmitted): string {
				// :: als Parameter-Trenner (Contao-konform), Flags nach | bereits herausgefiltert
				$parts = array_map('trim', explode('::', $matches[1]));

				// Alle Teile der Reihe nach als Feldname probieren
				foreach ($parts as $part) {
					if ($part === '') {
						continue;
					}
					if (array_key_exists($part, $arrSubmitted)) {
						$val = $arrSubmitted[$part];
						$val = is_array($val) ? implode(', ', $val) : (string) $val;

						if ($val !== '') {
							return htmlspecialchars($val);
						}
					}
				}

				// Kein Feld gefunden -> letzten Teil als literalen Fallback-Text anzeigen
				$fallback = end($parts);
				return ($fallback !== false && $fallback !== '') ? htmlspecialchars($fallback) : '';
			},
			$pattern
		) ?? '';
	}

	/**
	 * Generiert die Listenbezeichnung eines Eintrags.
	 * Zeigt Datum + Uhrzeit sowie – wenn am uebergeordneten Set ein label_field
	 * konfiguriert wurde – den aufgeloesten Wert des Anzeigemusters.
	 * Andernfalls wird die Empfaenger-Adresse als Fallback genutzt.
	 */
	public function generateLabel(array $row, string $label, $dc, array $args): string
	{
		$date = gmdate('d.m.Y H:i', (int) $row['tstamp']);

		// Anzeigemuster aus uebergeordnetem Set laden
		$set     = FormSubmissionsSetModel::findById($row['pid']);
		$pattern = ($set !== null && $set->label_field !== '') ? $set->label_field : '';

		$displayText = '';

		if ($pattern !== '') {
			$submissionData = FormSubmissionsDataModel::findOneBy('pid', $row['id']);

			if ($submissionData !== null) {
				$arrSubmitted = unserialize($submissionData->arrSubmitted, ['allowed_classes' => false]);

				if (is_array($arrSubmitted)) {
					$displayText = trim($this->resolvePattern($pattern, $arrSubmitted));
				}
			}
		}

		// Fallback: Empfaenger-Adresse
		if ($displayText === '') {
			$displayText = $row['recipient'] ? htmlspecialchars($row['recipient']) : '&mdash;';
		}

		return '<span style="color:var(--gray);padding-right:3px">[' . $date . ']</span> ' . $displayText;
	}

	/**
	 * Return the edit header button
	 */
	public function showForm($row, $href, $label, $title, $icon, $attributes)
	{
		return System::getContainer()->get('security.helper')->isGranted(ContaoCorePermissions::USER_CAN_EDIT_FIELDS_OF_TABLE, 'form_submissions_data') ? '<a href="' . $this->addToUrl($href . '&amp;popup=1&amp;showForm=' . (int) $row['id']) . '" title="' . StringUtil::specialchars($title) . '"' . $attributes . ' onclick="Backend.openModalIframe({\'title\':\'' . addslashes($title) . '\',\'url\':this.href});return false">' . Image::getHtml($icon, $label) . '</a> ' : Image::getHtml(str_replace('.svg', '--disabled.svg', $icon)) . ' ';
	}

	/**
	 * Return the "toggle resendForm" button
	 */
	public function resendForm($row, $href, $label, $title, $icon, $attributes)
	{
		return System::getContainer()->get('security.helper')->isGranted(ContaoCorePermissions::USER_CAN_EDIT_FIELDS_OF_TABLE, 'form_submissions_data') ? '<a href="' . $this->addToUrl($href . '&amp;popup=1&amp;resendForm=' . (int) $row['id']) . '" title="' . StringUtil::specialchars($title) . '"' . $attributes . ' onclick="Backend.openModalIframe({\'title\':\'' . addslashes($title) . '\',\'url\':this.href});return false">' . Image::getHtml($icon, $label, 'style="width:16px;height:auto;"') . '</a> ' : Image::getHtml(str_replace('.svg', '--disabled.svg', $icon)) . ' ';
	}

	/**
	 * Return Group Label
	 */
	public function groupCallback($group, $sortingMode, $firstOrderBy, $row, $dc)
	{
		$beginOfDay = strtotime("midnight", $row['tstamp']);
		$endOfDay   = strtotime("tomorrow", $beginOfDay) - 1;

		$result = $this->Database->prepare('SELECT id FROM tl_form_submissions WHERE pid=? AND tstamp BETWEEN ? AND ?')
			->execute($row['pid'], $beginOfDay, $endOfDay);
		$total = $result->numRows;

		$gmDate = gmdate("d.m.Y", $row['tstamp']);
		$gmDay  = gmdate("N", $row['tstamp']);

		$lang         = $GLOBALS['TL_LANG']['tl_form_submissions'];
		$messageLabel = ($total == 1)
			? ($lang['massage']  ?? '')
			: ($lang['massages'] ?? '');

		return '<div class="form_submissions_header"><span class="left">' . ($lang['days'][$gmDay] ?? '') . ', ' . $gmDate . ' </span><span class="right">(' . $total . ' ' . $messageLabel . ')</span></div>';
	}

	/**
	 * ondelete_callback – loescht auch die zugehoerigen Formulardaten
	 */
	public function deleteSubmission($dc)
	{
		$this->Database->prepare('DELETE FROM tl_form_submissions_data WHERE pid=? LIMIT 1')
			->execute($dc->id);
	}
}
