<?php

namespace PloverCRM\Core\Services;

use PloverCRM\Core\Container;
use PloverCRM\Core\Plugin;

/**
 * Email Guard Service
 * 
 * Protects the sender reputation by actively blocking outgoing emails to unsafe addresses.
 */
class EmailGuardService
{
  /**
   * @var Container
   */
  private $container;

  /**
   * Constructor
   * 
   * @param Container $container Dependency injection container
   */
  public function __construct(Container $container)
  {
    $this->container = $container;
  }

  /**
   * Initialize the service
   */
  public function init(): void
  {
    // Block outgoing emails to unsafe addresses
    add_filter('pre_wp_mail', [$this, 'validateOutgoingEmail'], 10, 2);
  }

  /**
   * Validate outgoing email before sending
   * 
   * Blocks emails to:
   * - @wpr.com placeholder addresses
   * - Emails that fail safety verification
   * - Contacts tagged with "Unverified Email"
   * 
   * @param null|bool $return Short-circuit return value
   * @param array $atts wp_mail arguments
   * @return null|bool False to block, null/true to allow (depending on context)
   */
  public function validateOutgoingEmail($return, array $atts)
  {
    $to_recipients = $atts['to'];
    if (is_array($to_recipients)) {
      $to_recipients = implode(',', $to_recipients);
    }

    // Block @wpr.com placeholder emails
    if (strpos($to_recipients, '@wpr.com') !== false) {
      return false;
    }

    // Extract email address for verification
    $email = $this->extractEmailAddress($to_recipients);
    if (empty($email)) {
      return $return;
    }

    // Check if contact has "Unverified Email" tag (already verified as unsafe)
    if ($this->hasUnverifiedEmailTag($email)) {
      return false;
    }

    // Verify email safety via API
    $isSafe = EmailVerificationService::isSafeToSend($email);

    if (!$isSafe) {
      // Tag contact as unverified to avoid future API calls
      $this->tagContactAsUnverified($email);
      return false;
    }

    return $return;
  }

  /**
   * Extract email address from recipient string
   * 
   * @param string $recipient Recipient string (e.g., "Name <email@example.com>" or "email@example.com")
   * @return string|null Email address or null if not found
   */
  private function extractEmailAddress(string $recipient): ?string
  {
    // Handle "Name <email@example.com>" format
    if (preg_match('/<(.+?)>/', $recipient, $matches)) {
      return trim($matches[1]);
    }

    // Handle plain email format
    if (filter_var(trim($recipient), FILTER_VALIDATE_EMAIL)) {
      return trim($recipient);
    }

    return null;
  }

  /**
   * Check if contact has "Unverified Email" tag
   * 
   * @param string $email Contact email
   * @return bool True if contact has the tag
   */
  private function hasUnverifiedEmailTag(string $email): bool
  {
    $crm = $this->container->get('crm');

    if (!$crm || !$crm->isAvailable()) {
      return false;
    }

    $contact = $crm->getContactByEmail($email);
    if (!$contact) {
      return false;
    }

    // Get all tags for the contact
    $tags = $crm->getContactTags($contact);

    // Check if "Unverified Email" tag exists
    foreach ($tags as $tag) {
      if (isset($tag['title']) && $tag['title'] === 'Unverified Email') {
        return true;
      }
    }

    return false;
  }

  /**
   * Tag contact as having unverified email
   * 
   * @param string $email Contact email
   */
  private function tagContactAsUnverified(string $email): void
  {
    try {
      $crm = $this->container->get('crm');

      if (!$crm || !$crm->isAvailable()) {
        return;
      }

      $contact = $crm->getContactByEmail($email);
      if (!$contact) {
        return;
      }

      // Get or create "Unverified Email" tag
      $tagId = $this->getOrCreateUnverifiedEmailTag($crm);
      if (!$tagId) {
        return;
      }

      // Get existing tags
      $existingTags = $contact['tags'] ?? [];
      $existingTagIds = array_column($existingTags, 'id');

      // Add new tag if not already present
      if (!in_array($tagId, $existingTagIds)) {
        $existingTagIds[] = $tagId;

        // Update contact with new tags
        $crm->createOrUpdateContact([
          'id' => $contact['id'],
          'email' => $email,
          'tags' => $existingTagIds,
        ]);
      }
    } catch (\Exception $e) {
    }
  }

  /**
   * Get or create "Unverified Email" tag
   * 
   * @param \PloverCRM\Core\CRM\CRMProviderInterface $crm CRM provider
   * @return int|null Tag ID or null if failed
   */
  private function getOrCreateUnverifiedEmailTag($crm): ?int
  {
    // Check if tag already exists
    try {
      $allTags = $crm->getAllTags();

      foreach ($allTags as $tag) {
        if ((isset($tag['slug']) && $tag['slug'] === 'unverified-email') ||
          (isset($tag['title']) && $tag['title'] === 'Unverified Email')
        ) {
          return $tag['id'];
        }
      }
    } catch (\Exception $e) {
    }

    // Create new tag
    try {
      $newTag = $crm->createTag([
        'title' => 'Unverified Email',
        'slug' => 'unverified-email',
        'description' => 'Email address failed safety verification',
      ]);

      if ($newTag && isset($newTag['id'])) {
        return $newTag['id'];
      } else {
        return null;
      }
    } catch (\Exception $e) {
      return null;
    }
  }
}
