from celery import shared_task
from app.utils.celery_app import celery
import smtplib
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
from datetime import datetime
import logging
import time
from flask import Flask
from app import create_app, mysql
from app.utils.company_settings import get_company_smtp_settings
import uuid
from app.utils.email_reply_scanner import scan_email_replies

# Configure logging
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)

@celery.task(bind=True)
def send_campaign_emails(self, campaign_id):
    """
    Send emails for a campaign using Hostinger SMTP (SSL, port 465)
    """
    # Ensure Flask app context
    app = create_app()
    with app.app_context():
        # logger.info(f"Starting to process campaign {campaign_id}")
        cursor = None

        try:
            cursor = mysql.connection.cursor()

            # Get campaign details
            cursor.execute("""
                SELECT c.*, comp.id as company_id
                FROM email_campaigns c
                JOIN companies comp ON c.company_id = comp.id
                WHERE c.id = %s
            """, (campaign_id,))
            campaign = cursor.fetchone()

            if not campaign:
                logger.error(f"Campaign {campaign_id} not found")
                return False

            # Update campaign status to sending
            cursor.execute("""
                UPDATE email_campaigns 
                SET status = 'sending', 
                    started_at = NOW() 
                WHERE id = %s
            """, (campaign_id,))
            mysql.connection.commit()

            company_id = campaign[-1]  # last column is company_id
            smtp_settings = get_company_smtp_settings(company_id)
            if not smtp_settings:
                raise Exception("SMTP settings not configured")

            mail_host = smtp_settings[1]
            mail_port = smtp_settings[2]
            mail_username = smtp_settings[3]
            mail_password = smtp_settings[4]
            mail_encryption = smtp_settings[5]
            mail_from_address = smtp_settings[6]
            mail_from_name = smtp_settings[7]

            # Get recipients
            cursor.execute("""
                SELECT cr.*, c.email, c.name
                FROM campaign_recipients cr
                JOIN contacts c ON cr.contact_id = c.id
                WHERE cr.campaign_id = %s AND cr.status = 'pending'
            """, (campaign_id,))
            recipients = cursor.fetchall()

            success_count = 0

            for recipient in recipients:
                try:
                    # logger.info(f"Preparing to send to {recipient[-2]}")
                    # Use SMTP_SSL for Hostinger (port 465)
                    with smtplib.SMTP_SSL(mail_host, int(mail_port), timeout=30) as smtp:
                        # logger.info("SMTP_SSL connection established")
                        smtp.login(mail_username, mail_password)
                        # logger.info("SMTP login successful")
                        msg = MIMEMultipart()
                        msg['From'] = f"{mail_from_name} <{mail_from_address}>"
                        msg['To'] = recipient[-2]
                        msg['Subject'] = campaign[4]
                        content = campaign[5].replace('{name}', recipient[-1])
                        msg.attach(MIMEText(content, 'html'))
                        msg_id = f"<{str(uuid.uuid4())}@{mail_host}>"
                        msg['Message-ID'] = msg_id
                        smtp.send_message(msg)
                        logger.info("Email sent")

                        try:
                            cursor.execute("""
                                UPDATE campaign_recipients
                                SET status = 'sent',
                                    sent_at = NOW(),
                                    message_id = %s
                                WHERE campaign_id = %s AND contact_id = %s
                            """, (msg_id, campaign_id, recipient[1]))
                            mysql.connection.commit()
                            logger.info(f"Stored message_id {msg_id} for campaign {campaign_id}, contact {recipient[1]}")
                        except Exception as e:
                            logger.error(f"Error updating campaign_recipients with message_id: {e}")

                    # Store the Message-ID in the database
                    cursor.execute("""
                        UPDATE email_campaigns
                        SET message_id = %s
                        WHERE id = %s
                    """, (msg['Message-ID'], campaign_id))
                    mysql.connection.commit()

                    success_count += 1
                    logger.info(f"Successfully sent email to {recipient[-2]}")
                    time.sleep(2)  # 2 second delay to avoid rate limits

                except Exception as e:
                    logger.error(f"Error sending to {recipient[-2]}: {str(e)}")
                    cursor.execute("""
                        UPDATE campaign_recipients
                        SET status = 'failed',
                            error_message = %s
                        WHERE campaign_id = %s AND contact_id = %s
                    """, (str(e), campaign_id, recipient[1]))
                    mysql.connection.commit()

            # Update campaign status
            final_status = 'completed' if success_count == len(recipients) else 'failed'
            cursor.execute("""
                UPDATE email_campaigns
                SET status = %s,
                    completed_at = NOW(),
                    sent_count = %s
                WHERE id = %s
            """, (final_status, success_count, campaign_id))
            mysql.connection.commit()

            logger.info(f"Campaign completed. Success count: {success_count}/{len(recipients)}")
            return True

        except Exception as e:
            logger.error(f"Campaign failed with error: {str(e)}")
            try:
                mysql.connection.ping(reconnect=True)
                cursor = mysql.connection.cursor()
                cursor.execute("""
                    UPDATE email_campaigns
                    SET status = 'failed',
                        error_message = %s
                    WHERE id = %s
                """, (str(e), campaign_id))
                mysql.connection.commit()
            except Exception as db_e:
                logger.error(f"Could not update campaign status due to DB error: {db_e}")
            raise e
        finally:
            if cursor:
                cursor.close()

@celery.on_after_configure.connect
def setup_periodic_tasks(sender, **kwargs):
    # Run every minute
    # sender.add_periodic_task(60.0, check_and_send_scheduled_campaigns.s(), name='Check scheduled campaigns every minute')
    # Add new task to check for replies every 5 minutes
    sender.add_periodic_task(60.0, scan_email_replies.s(), name='Scan for email replies every 5 minutes')

@celery.task
def check_and_send_scheduled_campaigns():
    app = create_app()
    with app.app_context():
        cursor = mysql.connection.cursor()
        now = datetime.now()
        # Find campaigns that are scheduled and due
        cursor.execute("""
            SELECT id FROM email_campaigns
            WHERE status = 'scheduled' AND scheduled_at IS NOT NULL AND scheduled_at <= NOW()
        """)
        due_campaigns = cursor.fetchall()
        for campaign in due_campaigns:
            campaign_id = campaign[0]
            # Set status to 'queued' to avoid double sending
            cursor.execute("""
                UPDATE email_campaigns
                SET status = 'queued'
                WHERE id = %s
            """, (campaign_id,))
            mysql.connection.commit()
            # Trigger the email sending task
            send_campaign_emails.delay(campaign_id)
        cursor.close()
