<?php declare(strict_types = 1);

namespace MailPoet\Abilities;

if (!defined('ABSPATH')) exit;


use Automattic\WooCommerce\Abilities\AbilityDefinition;
use MailPoet\AutomaticEmails\WooCommerce\Events\AbandonedCart;
use MailPoet\AutomaticEmails\WooCommerce\Events\FirstPurchase;
use MailPoet\AutomaticEmails\WooCommerce\Events\PurchasedInCategory;
use MailPoet\AutomaticEmails\WooCommerce\Events\PurchasedProduct;
use MailPoet\Automation\Engine\Storage\AutomationStorage;
use MailPoet\Automation\Integrations\MailPoet\Actions\SendEmailAction;
use MailPoet\Automation\Integrations\WooCommerce\Triggers\AbandonedCart\AbandonedCartTrigger;
use MailPoet\Automation\Integrations\WooCommerce\Triggers\BuysAProductTrigger;
use MailPoet\Automation\Integrations\WooCommerce\Triggers\BuysFromACategoryTrigger;
use MailPoet\Automation\Integrations\WooCommerce\Triggers\BuysFromATagTrigger;
use MailPoet\Config\AccessControl;
use MailPoet\Config\Hooks;
use MailPoet\DI\ContainerWrapper;
use MailPoet\Entities\SegmentEntity;
use MailPoet\Newsletter\NewslettersRepository;
use MailPoet\Segments\SegmentsRepository;
use MailPoet\Settings\SettingsController;
use MailPoet\Settings\TrackingConfig;
use MailPoet\WooCommerce\Helper as WooCommerceHelper;
use MailPoet\WooCommerce\Subscription;
use MailPoet\WooCommerce\TransactionalEmails;
use MailPoet\WP\Functions as WPFunctions;

if (!defined('ABSPATH')) exit;

if (!interface_exists(AbilityDefinition::class)) {
  return;
}

class WooCommerceMarketingStatus implements AbilityDefinition {
  private const TRACKING_LEVELS = [
    TrackingConfig::LEVEL_FULL,
    TrackingConfig::LEVEL_PARTIAL,
    TrackingConfig::LEVEL_BASIC,
  ];

  public static function get_name(): string { // phpcs:ignore PSR1.Methods.CamelCapsMethodName.NotCamelCaps -- Required by WooCommerce's AbilityDefinition interface.
    return 'mailpoet/get-woocommerce-marketing-status';
  }

  public static function get_registration_args(): array { // phpcs:ignore PSR1.Methods.CamelCapsMethodName.NotCamelCaps -- Required by WooCommerce's AbilityDefinition interface.
    return [
      'label' => __('Get MailPoet WooCommerce marketing status', 'mailpoet'),
      'description' => __('Read MailPoet WooCommerce marketing, checkout opt-in, and email editor status.', 'mailpoet'),
      'category' => 'woocommerce',
      'output_schema' => self::getOutputSchema(),
      'execute_callback' => [self::class, 'execute'],
      'permission_callback' => [self::class, 'canReadStatus'],
      'meta' => [
        'show_in_rest' => true,
        'mcp' => [
          'public' => true,
          'type' => 'tool',
        ],
        'annotations' => [
          'readonly' => true,
          'destructive' => false,
          'idempotent' => true,
        ],
      ],
    ];
  }

  public static function execute(): array {
    $container = ContainerWrapper::getInstance();

    /** @var SettingsController $settings */
    $settings = $container->get(SettingsController::class);
    /** @var WooCommerceHelper $woocommerceHelper */
    $woocommerceHelper = $container->get(WooCommerceHelper::class);
    /** @var NewslettersRepository $newslettersRepository */
    $newslettersRepository = $container->get(NewslettersRepository::class);
    /** @var SegmentsRepository $segmentsRepository */
    $segmentsRepository = $container->get(SegmentsRepository::class);
    /** @var AutomationStorage $automationStorage */
    $automationStorage = $container->get(AutomationStorage::class);

    $checkoutSegmentIds = array_values(array_unique(array_map('absint', (array)$settings->get(Subscription::OPTIN_SEGMENTS_SETTING_NAME, []))));
    $position = $settings->get(Subscription::OPTIN_POSITION_SETTING_NAME, Hooks::DEFAULT_OPTIN_POSITION);
    if (!is_string($position) || !array_key_exists($position, Hooks::OPTIN_HOOKS)) {
      $position = Hooks::DEFAULT_OPTIN_POSITION;
    }
    $trackingLevel = $settings->get('tracking.level', TrackingConfig::LEVEL_FULL);
    if (!is_string($trackingLevel) || !in_array($trackingLevel, self::TRACKING_LEVELS, true)) {
      $trackingLevel = TrackingConfig::LEVEL_FULL;
    }

    return [
      'checkout_optin' => [
        'enabled' => (bool)$settings->get(Subscription::OPTIN_ENABLED_SETTING_NAME, false),
        'message' => wp_strip_all_tags((string)$settings->get(Subscription::OPTIN_MESSAGE_SETTING_NAME, '')),
        'position' => $position,
        'segments' => self::formatSegments($segmentsRepository, $checkoutSegmentIds),
      ],
      'transactional_email_editor' => [
        'enabled' => (bool)$settings->get('woocommerce.use_mailpoet_editor', false),
        'template_configured' => absint($settings->get(TransactionalEmails::SETTING_EMAIL_ID, 0)) > 0,
      ],
      'legacy_automatic_emails' => [
        'active_counts' => [
          'abandoned_cart' => $newslettersRepository->getCountOfActiveAutomaticEmailsForEvent(AbandonedCart::SLUG),
          'first_purchase' => $newslettersRepository->getCountOfActiveAutomaticEmailsForEvent(FirstPurchase::SLUG),
          'purchased_in_category' => $newslettersRepository->getCountOfActiveAutomaticEmailsForEvent(PurchasedInCategory::SLUG),
          'purchased_product' => $newslettersRepository->getCountOfActiveAutomaticEmailsForEvent(PurchasedProduct::SLUG),
        ],
      ],
      'automations' => [
        'active_email_counts' => self::getAutomationEmailCounts($automationStorage),
      ],
      'measurement' => [
        'tracking_level' => $trackingLevel,
        'analytics_enabled' => (bool)$settings->get('analytics.enabled', false),
        'revenue_attribution_order_statuses' => $woocommerceHelper->getPurchaseStates(),
      ],
    ];
  }

  public static function canReadStatus(): bool {
    return WPFunctions::get()->currentUserCan(AccessControl::PERMISSION_MANAGE_SETTINGS);
  }

  private static function getOutputSchema(): array {
    return [
      'type' => 'object',
      'properties' => [
        'checkout_optin' => [
          'type' => 'object',
          'properties' => [
            'enabled' => ['type' => 'boolean'],
            'message' => ['type' => 'string'],
            'position' => [
              'type' => 'string',
              'enum' => array_keys(Hooks::OPTIN_HOOKS),
            ],
            'segments' => [
              'type' => 'array',
              'items' => [
                'type' => 'object',
                'properties' => [
                  'id' => ['type' => 'integer'],
                  'name' => ['type' => 'string'],
                ],
                'required' => ['id', 'name'],
                'additionalProperties' => false,
              ],
            ],
          ],
          'required' => ['enabled', 'message', 'position', 'segments'],
          'additionalProperties' => false,
        ],
        'transactional_email_editor' => [
          'type' => 'object',
          'properties' => [
            'enabled' => ['type' => 'boolean'],
            'template_configured' => ['type' => 'boolean'],
          ],
          'required' => ['enabled', 'template_configured'],
          'additionalProperties' => false,
        ],
        'legacy_automatic_emails' => [
          'type' => 'object',
          'properties' => [
            'active_counts' => [
              'type' => 'object',
              'properties' => [
                'abandoned_cart' => ['type' => 'integer'],
                'first_purchase' => ['type' => 'integer'],
                'purchased_in_category' => ['type' => 'integer'],
                'purchased_product' => ['type' => 'integer'],
              ],
              'required' => ['abandoned_cart', 'first_purchase', 'purchased_in_category', 'purchased_product'],
              'additionalProperties' => false,
            ],
          ],
          'required' => ['active_counts'],
          'additionalProperties' => false,
        ],
        'automations' => [
          'type' => 'object',
          'properties' => [
            'active_email_counts' => [
              'type' => 'object',
              'properties' => [
                'abandoned_cart' => ['type' => 'integer'],
                'order_completed' => ['type' => 'integer'],
                'order_created' => ['type' => 'integer'],
                'order_status_changed' => ['type' => 'integer'],
                'purchased_in_category' => ['type' => 'integer'],
                'purchased_product' => ['type' => 'integer'],
                'purchased_with_tag' => ['type' => 'integer'],
              ],
              'required' => ['abandoned_cart', 'order_completed', 'order_created', 'order_status_changed', 'purchased_in_category', 'purchased_product', 'purchased_with_tag'],
              'additionalProperties' => false,
            ],
          ],
          'required' => ['active_email_counts'],
          'additionalProperties' => false,
        ],
        'measurement' => [
          'type' => 'object',
          'properties' => [
            'tracking_level' => [
              'type' => 'string',
              'enum' => self::TRACKING_LEVELS,
            ],
            'analytics_enabled' => ['type' => 'boolean'],
            'revenue_attribution_order_statuses' => [
              'type' => 'array',
              'items' => ['type' => 'string'],
            ],
          ],
          'required' => ['tracking_level', 'analytics_enabled', 'revenue_attribution_order_statuses'],
          'additionalProperties' => false,
        ],
      ],
      'required' => ['checkout_optin', 'transactional_email_editor', 'legacy_automatic_emails', 'automations', 'measurement'],
      'additionalProperties' => false,
    ];
  }

  private static function formatSegments(SegmentsRepository $segmentsRepository, array $segmentIds): array {
    if (!$segmentIds) {
      return [];
    }

    $segmentsById = [];
    foreach ($segmentsRepository->findByIds($segmentIds) as $segment) {
      if (!$segment instanceof SegmentEntity || $segment->getId() === null) {
        continue;
      }
      $segmentsById[(int)$segment->getId()] = [
        'id' => (int)$segment->getId(),
        'name' => $segment->getName(),
      ];
    }

    $selectedSegments = [];
    foreach ($segmentIds as $segmentId) {
      if (isset($segmentsById[$segmentId])) {
        $selectedSegments[] = $segmentsById[$segmentId];
      }
    }

    return $selectedSegments;
  }

  private static function getAutomationEmailCounts(AutomationStorage $automationStorage): array {
    return [
      'abandoned_cart' => $automationStorage->getCountOfActiveByTriggerKeysAndAction([AbandonedCartTrigger::KEY], SendEmailAction::KEY),
      'order_completed' => $automationStorage->getCountOfActiveByTriggerKeysAndAction(['woocommerce:order-completed'], SendEmailAction::KEY),
      'order_created' => $automationStorage->getCountOfActiveByTriggerKeysAndAction(['woocommerce:order-created'], SendEmailAction::KEY),
      'order_status_changed' => $automationStorage->getCountOfActiveByTriggerKeysAndAction(['woocommerce:order-status-changed'], SendEmailAction::KEY),
      'purchased_in_category' => $automationStorage->getCountOfActiveByTriggerKeysAndAction([BuysFromACategoryTrigger::KEY], SendEmailAction::KEY),
      'purchased_product' => $automationStorage->getCountOfActiveByTriggerKeysAndAction([BuysAProductTrigger::KEY], SendEmailAction::KEY),
      'purchased_with_tag' => $automationStorage->getCountOfActiveByTriggerKeysAndAction([BuysFromATagTrigger::KEY], SendEmailAction::KEY),
    ];
  }
}
