<?php

namespace GriffinForms\Includes\Notifications;

use GriffinForms\Traits\Singleton;

class NotificationChannelRegistry
{
    use Singleton;

    /** @var NotificationChannelInterface[] Ordered list of registered channels. */
    private array $channels = [];

    private static function getEmptyNotificationsMap(): array
    {
        return [
            'form_submission' => [
                'initial_submission' => [],
                'submission_edit'    => [],
            ],
            'payment_received' => [
                'payment_success' => [],
                'payment_failed'  => [],
            ],
        ];
    }

    public function register(NotificationChannelInterface $channel): void
    {
        $this->channels[$channel->getChannelId()] = $channel;
    }

    /** @return NotificationChannelInterface[] */
    public function getAll(): array
    {
        return array_values($this->channels);
    }

    public function get(string $channel_id): ?NotificationChannelInterface
    {
        return $this->channels[$channel_id] ?? null;
    }

    /**
     * Return the decoded notifications map for a form, merging legacy columns as fallback.
     *
     * 1. If the notifications column is populated — decode and return it.
     * 2. Otherwise — build from legacy autoresponder and alert_emails columns.
     *
     * @param array|\stdClass $form_props Form row as array or object (supports getProp() objects too).
     */
    public static function resolveFormNotifications($form_props): array
    {
        $get = static function(string $key) use ($form_props) {
            if (is_object($form_props) && method_exists($form_props, 'getProp')) {
                return $form_props->getProp($key);
            }
            if (is_array($form_props)) {
                return $form_props[$key] ?? null;
            }
            if (is_object($form_props)) {
                return $form_props->$key ?? null;
            }
            return null;
        };

        $notifications_raw = $get('notifications');
        if (!empty($notifications_raw) && is_array($notifications_raw)) {
            return $notifications_raw;
        }
        if (!empty($notifications_raw) && is_string($notifications_raw)) {
            $decoded = json_decode($notifications_raw, true);
            if (is_array($decoded)) {
                return $decoded;
            }
        }

        // Legacy fallback: synthesize the v2 notifications map from old columns.
        $map   = self::getEmptyNotificationsMap();
        $order = 1;

        $autoresponder = $get('autoresponder');
        if (!empty($autoresponder)) {
            $decoded = is_string($autoresponder) ? json_decode($autoresponder, true) : null;
            if (is_array($decoded)) {
                foreach ($decoded as $mapping) {
                    if (!is_array($mapping)) {
                        continue;
                    }

                    $field_id   = absint($mapping['email_field_id'] ?? 0);
                    $message_id = absint($mapping['message_id'] ?? 0);

                    if ($field_id <= 0) {
                        continue;
                    }

                    $map['form_submission']['initial_submission'][] = [
                        'id'         => 'legacy-ar-' . $order,
                        'order'      => $order++,
                        'enabled'    => true,
                        'channel'    => 'email',
                        'message_id' => $message_id,
                        'recipients' => [
                            ['type' => 'field', 'value' => (string) $field_id],
                        ],
                    ];
                }
            }
        }

        $alert_emails = $get('alert_emails');
        if (!empty($alert_emails) && is_array($alert_emails)) {
            $is_assoc = array_keys($alert_emails) !== range(0, count($alert_emails) - 1);
            if ($is_assoc) {
                foreach ($alert_emails as $email => $message_id) {
                    $email = sanitize_email((string) $email);
                    if ($email === '') {
                        continue;
                    }

                    $map['form_submission']['initial_submission'][] = [
                        'id'         => 'legacy-alert-' . $order,
                        'order'      => $order++,
                        'enabled'    => true,
                        'channel'    => 'email',
                        'message_id' => absint($message_id),
                        'recipients' => [
                            ['type' => 'static', 'value' => $email],
                        ],
                    ];
                }
            } else {
                foreach ($alert_emails as $email) {
                    $email = sanitize_email((string) $email);
                    if ($email === '') {
                        continue;
                    }

                    $map['form_submission']['initial_submission'][] = [
                        'id'         => 'legacy-alert-' . $order,
                        'order'      => $order++,
                        'enabled'    => true,
                        'channel'    => 'email',
                        'message_id' => 0,
                        'recipients' => [
                            ['type' => 'static', 'value' => $email],
                        ],
                    ];
                }
            }
        }

        return $map;
    }
}
