<?php

namespace FluentBooking\Framework\Support;

use InvalidArgumentException;
use FluentBooking\Framework\Foundation\App;
use FluentBooking\Framework\View\View;

class Mail
{
    protected array $to = [];
    protected array $cc = [];
    protected array $bcc = [];
    protected string $from = '';
	protected string $fromName = '';
    protected string $subject = '';
    protected string $body = '';
    protected array $headers = [];
    protected array $attachments = [];
    protected string $contentType = 'text/html';

    /**
     * Set one or more recipients.
     *
     * @param string|array $emails
     * @return $this
     */
	public function to($emails)
    {
        $this->to = (array) $emails;
        return $this;
    }

    /**
     * Set the email sender.
     * 
     * @param  string      $email
     * @param  string|null $name
     * @return $this
     */
    public function from($email, $name = null)
    {
        $this->from = $email;
        $this->fromName = $name ?: get_bloginfo('name');
        return $this;
    }

    /**
     * Set one or more CC recipients.
     *
     * @param string|array $emails
     * @return $this
     */
    public function cc($emails)
    {
        $this->cc = array_merge($this->cc, (array) $emails);
        return $this;
    }

    /**
     * Set one or more BCC recipients.
     *
     * @param string|array $emails
     * @return $this
     */
    public function bcc($emails)
    {
        $this->bcc = array_merge($this->bcc, (array) $emails);
        return $this;
    }

    /**
     * Set the email subject.
     *
     * @param string $subject
     * @return $this
     */
    public function subject($subject)
    {
        $this->subject = $subject;
        return $this;
    }

    /**
     * Set the email body (HTML or plain text).
     *
     * @param string $body
     * @return $this
     */
    public function body($body)
    {
        $this->body = $body;
        return $this;
    }

    /**
     * Set the body from a PHP template file with optional data.
     *
     * @param string $templatePath
     * @param array $data
     * @return $this
     */
    public function view($templatePath, $data = [])
    {
        $this->body = App::make(View::class)->make($templatePath, $data);

        $this->contentType('text/html');

        return $this;
    }

    /**
     * Add or override headers.
     *
     * @param array|string $headers
     * @param string|null $value
     * @return $this
     */
    public function withHeader($headers, $value = null)
    {
        if (is_array($headers)) {
            $this->headers = array_merge($this->headers, $headers);
        } else {
            $this->headers[$headers] = $value;
        }

        return $this;
    }

    /**
     * Set Content-Type header (default is text/html).
     *
     * @param string $contentType
     * @return $this
     */
    public function contentType($contentType)
    {
        $this->contentType = $contentType;
        
        return $this;
    }

    /**
     * Attach one or more files.
     *
     * @param string|array $paths
     * @return $this
     */
    public function attach($paths)
    {
        $paths = (array) $paths;
        foreach ($paths as $path) {
            if (!file_exists($path)) {
                throw new InvalidArgumentException(
                	"Attachment file not found: {$path}"
                );
            }
            $this->attachments[] = $path;
        }

        return $this;
    }

    /**
     * Prepare headers for wp_mail.
     *
     * @return array
     */
    protected function prepareHeaders()
    {
        $headers = [];

        // Note: We removed Content-Type and From from here 
        // because we handle them via filters in send() now.
        // This prevents duplicate headers which triggers some spam filters.

        if (!empty($this->cc)) {
            $headers[] = 'Cc: ' . implode(', ', $this->cc);
        }

        if (!empty($this->bcc)) {
            $headers[] = 'Bcc: ' . implode(', ', $this->bcc);
        }

        foreach ($this->headers as $key => $value) {
            $headers[] = is_int($key) ? $value : "{$key}: {$value}";
        }

        return $headers;
    }

    /**
     * Send the email immediately.
     *
     * @return bool
     */
    public function send()
    {
        if (empty($this->to)) {
            throw new InvalidArgumentException(
                "At least one recipient (to) must be specified."
            );
        }

        // 1. Set Content Type Filter
        $contentType = function() { return $this->contentType; };
        add_filter('wp_mail_content_type', $contentType);

        // 2. Set From Filters (if provided)
        $fromEmailFilter = fn() => $this->from ?: get_bloginfo('admin_email');
        $fromNameFilter  = fn() => $this->fromName ?: get_bloginfo('name');
        
        if ($this->from) {
            add_filter('wp_mail_from', $fromEmailFilter);
            add_filter('wp_mail_from_name', $fromNameFilter);
        }

        $to = implode(', ', $this->to);
        $headers = $this->prepareHeaders();

        $result = wp_mail(
            $to,
            $this->subject,
            $this->body,
            $headers,
            $this->attachments
        );

        // 3. Clean up filters so we don't affect other emails
        remove_filter('wp_mail_content_type', $contentType);
        
        if ($this->from) {
            remove_filter('wp_mail_from', $fromEmailFilter);
            remove_filter('wp_mail_from_name', $fromNameFilter);
        }

        return $result;
    }

    /**
     * Static helper to start a new mail instance.
     *
     * @return static
     */
    public static function make()
    {
        return new static();
    }
}
