<?php

namespace App\Modules\Admin;

use Illuminate\Support\Facades\Input;
use Illuminate\Support\Facades\View;
use App\Facades\DBconfig;
use Illuminate\Support\Facades\Redirect;
use Illuminate\Support\Facades\Session;
use Exception;
use App\Http\Controllers\BaseController;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Mail;
use Illuminate\Support\Facades\Config;

class EmailsController extends BaseController
{
    /**
     *	The layout that should be used for responses.
     */
    protected $layout = 'layouts.master';

    /**
     * Render the ldap settings page.
     *
     * @return null
     */
    public function index()
    {
        $emails = EmailSettings::all();
        $settings = DBconfig::get('emails');

        $this->layout->content = View::make('admin::settings.emails.index', compact('emails', 'settings'));
    }

    /**
     * Display the page for creating a new email.
     *
     * @return null
     */
    public function create()
    {
        $this->layout->content = View::make('admin::settings.emails.create');
    }

    /**
     * Creates a new email.
     *
     * @return Illuminate\Support\Response
     */
    public function store()
    {
        $email = EmailSettings::create(request()->all());

        if (! $email->exists) {
            return Redirect::route('admin.settings.emails.create')->withError($email);
        }

        return Redirect::route('admin.settings.emails.index')->with('message', 'Email added successfully.');
    }

    /**
     * Display the edit a email page.
     *
     * @param  int $id
     *
     * @return null
     */
    public function edit($id)
    {
        $email = EmailSettings::findOrFail($id);
        $this->layout->content = View::make('admin::settings.emails.edit', compact('email'));
    }

    /**
     * Updates an existing email.
     *
     * @param  int $id
     *
     * @return null
     */
    public function update($id)
    {
        $email = EmailSettings::findOrFail($id);
        $email->fill(request()->all());
        if (! $email->save()) {
            return Redirect::route('admin.settings.emails.edit', $id)->withError($email);
        }

        return Redirect::route('admin.settings.emails.edit', $id)->with('message', 'Your changes were successfully saved.');
    }

    /**
     * Delete an email address.
     *
     * @param  string $id
     *
     * @return array
     */
    public function destroy($id)
    {
        $email = EmailSettings::findOrFail($id);

        if (! $email->delete()) {
            throw new Exception('Failed to delete the email address');
        }

        Session::flash('message', 'The email address <em>'.$email->email.'</em> has been successfully deleted');

        return $email;
    }

    /**
     * Enables the module.
     *
     * @return array
     */
    public function enable()
    {
        DBconfig::store('emails.enabled', true);

        return [
            'enabled' => true,
            'message' => 'The module has been enabled successfully',
        ];
    }

    /**
     * Disables the module.
     *
     * @return array
     */
    public function disable()
    {
        DBconfig::store('emails.enabled', false);

        return [
            'enabled' => false,
            'message' => 'The module has been disabled successfully',
        ];
    }

    /**
     * Test IMAP connection
     *
     * @return array
     */
    public function testImapConnection()
    {
        try {
            $server = request('server');
            $port = request('port');
            $protocol = request('protocol');
            $username = request('username');
            $password = request('password');

            // Validate required fields
            if (!$server || !$port || !$protocol || !$username || !$password) {
                return response()->json([
                    'success' => false,
                    'message' => 'All IMAP fields are required for testing.'
                ]);
            }

            // Test connection using socket
            $useSSL = ($port == 993 && strtolower($protocol) === 'imap') || ($port == 995 && strtolower($protocol) === 'pop3');
            
            // Create socket connection
            $context = stream_context_create([
                'ssl' => [
                    'verify_peer' => false,
                    'verify_peer_name' => false,
                    'allow_self_signed' => true
                ]
            ]);
            
            $socket = @stream_socket_client(
                ($useSSL ? 'ssl://' : '') . $server . ':' . $port,
                $errno,
                $errstr,
                10,
                STREAM_CLIENT_CONNECT,
                $context
            );
            
            if (!$socket) {
                return response()->json([
                    'success' => false,
                    'message' => 'Connection failed: ' . $errstr . ' (Error: ' . $errno . ')'
                ]);
            }

            // Read initial response
            $response = fgets($socket, 1024);
            
            if (!$response) {
                fclose($socket);
                return response()->json([
                    'success' => false,
                    'message' => 'No response from server'
                ]);
            }

            // Attempt authentication based on protocol
            if (strtolower($protocol) === 'imap') {
                // IMAP authentication
                fwrite($socket, "A001 LOGIN $username $password\r\n");
                $authResponse = fgets($socket, 1024);
                
                if (strpos($authResponse, 'A001 OK') !== false) {
                    // Get message count
                    fwrite($socket, "A002 SELECT INBOX\r\n");
                    $selectResponse = '';
                    while ($line = fgets($socket, 1024)) {
                        $selectResponse .= $line;
                        if (strpos($line, 'A002 OK') !== false) {
                            break;
                        }
                    }
                    
                    // Extract message count
                    $messageCount = 0;
                    if (preg_match('/\* (\d+) EXISTS/', $selectResponse, $matches)) {
                        $messageCount = $matches[1];
                    }
                    
                    fwrite($socket, "A003 LOGOUT\r\n");
                    fclose($socket);
                    
                    return response()->json([
                        'success' => true,
                        'message' => 'IMAP connection successful! Found ' . $messageCount . ' messages in inbox.'
                    ]);
                } else {
                    fclose($socket);
                    return response()->json([
                        'success' => false,
                        'message' => 'IMAP authentication failed: ' . trim($authResponse)
                    ]);
                }
            } elseif (strtolower($protocol) === 'pop3') {
                // POP3 authentication
                fwrite($socket, "USER $username\r\n");
                $userResponse = fgets($socket, 1024);
                
                if (strpos($userResponse, '+OK') === 0) {
                    fwrite($socket, "PASS $password\r\n");
                    $passResponse = fgets($socket, 1024);
                    
                    if (strpos($passResponse, '+OK') === 0) {
                        // Get message count
                        fwrite($socket, "STAT\r\n");
                        $statResponse = fgets($socket, 1024);
                        
                        $messageCount = 0;
                        if (preg_match('/\+OK (\d+)/', $statResponse, $matches)) {
                            $messageCount = $matches[1];
                        }
                        
                        fwrite($socket, "QUIT\r\n");
                        fclose($socket);
                        
                        return response()->json([
                            'success' => true,
                            'message' => 'POP3 connection successful! Found ' . $messageCount . ' messages in mailbox.'
                        ]);
                    } else {
                        fclose($socket);
                        return response()->json([
                            'success' => false,
                            'message' => 'POP3 password authentication failed: ' . trim($passResponse)
                        ]);
                    }
                } else {
                    fclose($socket);
                    return response()->json([
                        'success' => false,
                        'message' => 'POP3 username authentication failed: ' . trim($userResponse)
                    ]);
                }
            }

            return response()->json([
                'success' => false,
                'message' => 'Unsupported protocol: ' . $protocol
            ]);

        } catch (\Exception $e) {
            Log::error('IMAP connection test failed: ' . $e->getMessage());
            
            return response()->json([
                'success' => false,
                'message' => 'IMAP connection failed: ' . $e->getMessage()
            ]);
        }
    }

    /**
     * Test SMTP connection
     *
     * @return array
     */
    public function testSmtpConnection()
    {
        try {
            $smtpHost = request('smtp_host');
            $smtpPort = request('smtp_port', 587);
            $smtpEncryption = request('smtp_encryption', 'tls');
            $smtpUsername = request('smtp_username');
            $smtpPassword = request('smtp_password');
            $smtpFromName = request('smtp_from_name', 'Test');
            $smtpFromAddress = request('smtp_from_address');
            $email = request('email');
            $smtpTestTo = request('smtp_test_to');

            // Validate required fields
            if (!$smtpHost || !$smtpUsername || !$smtpPassword || !$email) {
                return response()->json([
                    'success' => false,
                    'message' => 'SMTP Host, Username, Password, and Email fields are required for testing.'
                ]);
            }
            
            // Require test email for SMTP testing
            if (empty($smtpTestTo)) {
                return response()->json([
                    'success' => false,
                    'message' => 'Test To Address field is required for SMTP testing.'
                ]);
            }

            // Store original mail configuration (older Laravel version)
            $originalDriver = Config::get('mail.driver');
            $originalHost = Config::get('mail.host');
            $originalPort = Config::get('mail.port');
            $originalEncryption = Config::get('mail.encryption');
            $originalUsername = Config::get('mail.username');
            $originalPassword = Config::get('mail.password');
            $originalFromAddress = Config::get('mail.from.address');
            $originalFromName = Config::get('mail.from.name');

            // Force SMTP driver and set test configuration
            Config::set('mail.driver', 'smtp');
            Config::set('mail.host', $smtpHost);
            Config::set('mail.port', $smtpPort);
            Config::set('mail.encryption', $smtpEncryption ?: null);
            Config::set('mail.username', $smtpUsername);
            Config::set('mail.password', $smtpPassword);
            Config::set('mail.from.address', $smtpFromAddress ?: $email);
            Config::set('mail.from.name', $smtpFromName);

            // Clear mail manager cache to force new configuration
            app()->forgetInstance('mail.manager');
            app()->forgetInstance('mailer');

            // Get CC and BCC for test
            $smtpCc = request('smtp_cc');
            $smtpBcc = request('smtp_bcc');

            // Use the required test email
            $testToEmail = $smtpTestTo;
            
            // Test by sending a test email
            $emailBody = 'This is a test email to verify SMTP configuration.' . "\n\n";
            $emailBody .= 'Test settings:' . "\n";
            $emailBody .= 'SMTP Host: ' . $smtpHost . "\n";
            $emailBody .= 'SMTP Port: ' . $smtpPort . "\n";
            $emailBody .= 'From Address: ' . ($smtpFromAddress ?: $email) . "\n";
            $emailBody .= 'To Address: ' . $testToEmail . "\n";
            $emailBody .= '(Using Test To Address field - required for SMTP testing)' . "\n";
            
            Mail::raw($emailBody, function ($message) use ($testToEmail, $smtpFromName, $smtpFromAddress, $email, $smtpCc, $smtpBcc) {
                $message->to($testToEmail)
                       ->subject('SMTP Test - ' . date('Y-m-d H:i:s'))
                       ->from($smtpFromAddress ?: $email, $smtpFromName);
                
                // Add CC recipients if specified
                if ($smtpCc) {
                    $ccEmails = array_map('trim', explode(',', $smtpCc));
                    $ccEmails = array_filter($ccEmails); // Remove empty entries
                    if (!empty($ccEmails)) {
                        $message->cc($ccEmails);
                    }
                }
                
                // Add BCC recipients if specified
                if ($smtpBcc) {
                    $bccEmails = array_map('trim', explode(',', $smtpBcc));
                    $bccEmails = array_filter($bccEmails); // Remove empty entries
                    if (!empty($bccEmails)) {
                        $message->bcc($bccEmails);
                    }
                }
            });

            // Restore original configuration
            Config::set('mail.driver', $originalDriver);
            Config::set('mail.host', $originalHost);
            Config::set('mail.port', $originalPort);
            Config::set('mail.encryption', $originalEncryption);
            Config::set('mail.username', $originalUsername);
            Config::set('mail.password', $originalPassword);
            Config::set('mail.from.address', $originalFromAddress);
            Config::set('mail.from.name', $originalFromName);

            $successMessage = 'SMTP connection successful! Test email sent to ' . $testToEmail;
            
            return response()->json([
                'success' => true,
                'message' => $successMessage
            ]);

        } catch (\Exception $e) {
            // Restore original configuration in case of error
            if (isset($originalHost)) {
                Config::set('mail.driver', $originalDriver);
                Config::set('mail.host', $originalHost);
                Config::set('mail.port', $originalPort);
                Config::set('mail.encryption', $originalEncryption);
                Config::set('mail.username', $originalUsername);
                Config::set('mail.password', $originalPassword);
                Config::set('mail.from.address', $originalFromAddress);
                Config::set('mail.from.name', $originalFromName);
            }

            Log::error('SMTP connection test failed: ' . $e->getMessage());
            
            return response()->json([
                'success' => false,
                'message' => 'SMTP connection failed: ' . $e->getMessage()
            ]);
        }
    }
}
