<?php

declare(strict_types=1);

namespace MauticPlugin\DealFlowBundle\Controller\Helper;

use Symfony\Component\HttpFoundation\Request;

/**
 * Stateless helper for parsing deal-related HTTP request data.
 *
 * All methods are static to enable reuse across the split controller classes
 * without requiring DI or service registration.
 */
final class DealRequestParser
{
    /**
     * Parses contact rows submitted via the deal form.
     *
     * @return list<array{contact_id:?int, contact_name:string, label:string}>
     */
    public static function resolveSubmittedContactRows(Request $request): array
    {
        $submittedRows = $request->request->all('deal_contacts');
        if (!is_array($submittedRows)) {
            return self::ensureContactRows([]);
        }

        $rows = [];

        foreach ($submittedRows as $row) {
            if (!is_array($row)) {
                continue;
            }

            $contactId = isset($row['contact_id']) ? (int) $row['contact_id'] : 0;
            $contactName = trim((string) ($row['contact_name'] ?? ''));
            $label = self::resolveSubmittedContactLabel($row);

            if ($contactId <= 0 && '' === $contactName && '' === $label) {
                continue;
            }

            $rows[] = [
                'contact_id' => $contactId > 0 ? $contactId : null,
                'contact_name' => $contactName,
                'label' => $label,
            ];
        }

        return self::ensureContactRows($rows);
    }

    /**
     * Resolves the label from a submitted contact row, handling the
     * label_selection / label_custom / legacy label fields.
     *
     * @param array<string, mixed> $row
     */
    public static function resolveSubmittedContactLabel(array $row): string
    {
        $selectedLabel = trim((string) ($row['label_selection'] ?? ''));
        $customLabel = trim((string) ($row['label_custom'] ?? ''));
        $legacyLabel = trim((string) ($row['label'] ?? ''));

        if ('__custom__' === $selectedLabel) {
            return '' !== $customLabel ? $customLabel : $legacyLabel;
        }

        if ('' !== $selectedLabel) {
            return $selectedLabel;
        }

        if ('' !== $customLabel) {
            return $customLabel;
        }

        return $legacyLabel;
    }

    /**
     * Ensures at least one empty contact row is present.
     *
     * @param list<array{contact_id:?int, contact_name:string, label:string}> $rows
     *
     * @return list<array{contact_id:?int, contact_name:string, label:string}>
     */
    public static function ensureContactRows(array $rows): array
    {
        return [] !== $rows ? $rows : [[
            'contact_id' => null,
            'contact_name' => '',
            'label' => '',
        ]];
    }

    /**
     * Builds contact rows from the deal context data (for edit form pre-population).
     *
     * @param array<int, array{id:int, label:?string, name:string, email:?string}> $contacts
     *
     * @return list<array{contact_id:?int, contact_name:string, label:string}>
     */
    public static function buildContactRowsFromContext(array $contacts): array
    {
        $rows = [];

        foreach ($contacts as $contact) {
            $rows[] = [
                'contact_id' => (int) $contact['id'],
                'contact_name' => trim(sprintf('%s%s', $contact['name'], $contact['email'] ? ' ('.$contact['email'].')' : '')),
                'label' => trim((string) ($contact['label'] ?? '')),
            ];
        }

        return self::ensureContactRows($rows);
    }

    /**
     * Validates contact rows, returning a list of error messages.
     *
     * @param list<array{contact_id:?int, contact_name:string, label:string}> $rows
     *
     * @return list<string>
     */
    public static function validateContactRows(array $rows): array
    {
        $errors = [];
        $seenContactIds = [];

        foreach ($rows as $row) {
            $contactId = $row['contact_id'];
            $contactName = trim($row['contact_name']);
            $label = trim($row['label']);

            if (null === $contactId && ('' !== $contactName || '' !== $label)) {
                $errors[] = 'Select each stakeholder from the contact lookup list.';
                continue;
            }

            if (null !== $contactId) {
                if (isset($seenContactIds[$contactId])) {
                    $errors[] = 'Each contact can only be associated with the deal once.';
                    continue;
                }

                $seenContactIds[$contactId] = true;
            }
        }

        return array_values(array_unique($errors));
    }

    /**
     * Builds the payload for DealManager::syncContactAssociations().
     *
     * @param list<array{contact_id:?int, contact_name:string, label:string}> $rows
     *
     * @return list<array{contact_id:int, label:?string}>
     */
    public static function buildContactSyncPayload(array $rows): array
    {
        $payload = [];

        foreach ($rows as $row) {
            if (null === $row['contact_id'] || $row['contact_id'] <= 0) {
                continue;
            }

            $payload[] = [
                'contact_id' => (int) $row['contact_id'],
                'label' => '' !== trim($row['label']) ? trim($row['label']) : null,
            ];
        }

        return $payload;
    }

    /**
     * Extracts submitted custom field values from the request.
     *
     * @return array<string, mixed>
     */
    public static function resolveCustomFieldInputs(Request $request): array
    {
        $values = $request->request->all('dealflow_custom_fields');

        return is_array($values) ? $values : [];
    }
}
