#!/usr/bin/env python3

import subprocess
import sys
import time
import logging
from datetime import datetime
import os
import smtplib
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
from dotenv import load_dotenv

# Load environment variables from .env file
load_dotenv()

# Configure logging
logging.basicConfig(
    level=logging.INFO,
    format='%(asctime)s - %(levelname)s - %(message)s',
    handlers=[
        logging.FileHandler("gymleco/manager.log", mode='w', encoding='utf-8'),
        logging.StreamHandler(sys.stdout)
    ]
)


def send_error_notification(error_message, script_name="Unknown"):
    """
    Send email notification when an error occurs
    """
    try:
        # Email configuration
        sender_email = "price.monitor.email@gmail.com"
        receiver_email = "price.monitor.email@gmail.com"
        password = os.getenv('EMAIL_PASSWORD')

        if not password:
            logging.error("❌ EMAIL_PASSWORD not found in environment variables")
            return False

        # Create message
        message = MIMEMultipart()
        message["From"] = sender_email
        message["To"] = receiver_email
        message["Subject"] = "Gymleco Error"

        # Email body
        body = f"""
Gymleco Scraper Error Report
============================

Script: {script_name}
Time: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}

Error Details:
{error_message}
        """

        message.attach(MIMEText(body, "plain"))

        # Create SMTP session
        with smtplib.SMTP("smtp.gmail.com", 587) as server:
            server.starttls()  # Enable security
            server.login(sender_email, password)
            text = message.as_string()
            server.sendmail(sender_email, receiver_email, text)

        logging.info("✅ Error notification email sent successfully")
        return True

    except Exception as e:
        logging.error(f"❌ Failed to send error notification email: {str(e)}")
        return False


def run_script(script_name, description):
    """
    Run a script and capture its output, sending email notification on failure
    """
    try:
        logging.info(f"Starting {description}...")

        # Start the process
        process = subprocess.Popen(
            ['/home/Script/Script_env/bin/python3.12', script_name],
            stdout=subprocess.PIPE,
            stderr=subprocess.PIPE,
            text=True,
            bufsize=1,
            universal_newlines=True
        )

        # Capture output for potential error reporting
        stdout_lines = []
        stderr_lines = []

        # Real-time output streaming
        while True:
            output = process.stdout.readline()
            if output == '' and process.poll() is not None:
                break
            if output:
                print(output.strip())
                stdout_lines.append(output.strip())

        # Wait for process to complete
        return_code = process.wait()

        # Get any remaining stderr output
        stderr_output = process.stderr.read()
        if stderr_output:
            stderr_lines.extend(stderr_output.strip().split('\n'))
            logging.error(f"Error output from {script_name}:\n{stderr_output}")

        if return_code == 0:
            logging.info(f"✅ {description} completed successfully!")
            return True
        else:
            logging.error(f"❌ {description} failed with return code: {return_code}")

            # Prepare error message for email
            error_details = []
            error_details.append(f"Script: {script_name}")
            error_details.append(f"Description: {description}")
            error_details.append(f"Return Code: {return_code}")

            if stderr_lines:
                error_details.append("\nError Output:")
                error_details.extend(stderr_lines[-10:])  # Last 10 lines of stderr

            if stdout_lines:
                error_details.append("\nLast Output Lines:")
                error_details.extend(stdout_lines[-5:])  # Last 5 lines of stdout

            error_message = "\n".join(error_details)

            # Send error notification
            send_error_notification(error_message, script_name)

            return False

    except FileNotFoundError:
        error_msg = f"Script {script_name} not found!"
        logging.error(f"❌ {error_msg}")
        send_error_notification(error_msg, script_name)
        return False
    except Exception as e:
        error_msg = f"Error running {script_name}: {str(e)}"
        logging.error(f"❌ {error_msg}")
        send_error_notification(error_msg, script_name)
        return False


def check_file_exists(filename):
    """Check if a required file exists"""
    if os.path.exists(filename):
        return True
    else:
        logging.warning(f"⚠️  {filename} not found")
        return False


def check_environment():
    """Check if required environment variables are set"""
    email_password = os.getenv('EMAIL_PASSWORD')
    if not email_password:
        error_msg = "EMAIL_PASSWORD not found in .env file. Please add EMAIL_PASSWORD=your_app_password to your .env file"
        logging.error(f"❌ {error_msg}")
        return False

    logging.info("✅ Environment variables checked successfully")
    return True


def main():
    """Main execution function"""
    start_time = datetime.now()

    logging.info("=" * 50)
    logging.info("GYMLECO SCRAPER MANAGER STARTED")
    logging.info("=" * 50)

    # Check environment variables
    if not check_environment():
        logging.error("❌ Environment check failed. Exiting.")
        sys.exit(1)

    # Check if required scripts exist
    scripts_exist = True
    if not check_file_exists("gymleco/gymleco_products.py"):
        scripts_exist = False
    if not check_file_exists("gymleco/gymleco_details.py"):
        scripts_exist = False

    if not scripts_exist:
        error_msg = "Required script files not found. Expected: gymleco_products.py, gymleco_details.py"
        logging.error(f"❌ {error_msg}")
        send_error_notification(error_msg, "File Check")
        sys.exit(1)

    # Step 1: Run product listing scraper
    logging.info("=" * 40)
    logging.info("STEP 1: PRODUCT LISTING SCRAPER")
    logging.info("=" * 40)

    success_products = run_script("gymleco/gymleco_products.py", "Product listing scraper")

    if not success_products:
        logging.error("❌ Product listing scraper failed. Cannot proceed to details scraper.")
        sys.exit(1)

    if not check_file_exists("gymleco/products.xlsx"):
        error_msg = "products.xlsx not found after running product scraper. Cannot proceed."
        logging.error(f"❌ {error_msg}")
        send_error_notification(error_msg, "Product Scraper Output Check")
        sys.exit(1)

    # Add a small delay between scripts
    time.sleep(5)

    # Step 2: Run product details scraper
    logging.info("=" * 40)
    logging.info("STEP 2: PRODUCT DETAILS SCRAPER")
    logging.info("=" * 40)

    success_details = run_script("gymleco/gymleco_details.py", "Product details scraper")

    # Final summary
    end_time = datetime.now()
    duration = end_time - start_time

    logging.info("=" * 50)
    logging.info("EXECUTION SUMMARY")
    logging.info("=" * 50)
    logging.info(f"Total execution time: {duration}")

    if success_products and success_details:
        logging.info("✅ All scrapers completed successfully!")

        # List generated files
        generated_files = []
        for filename in ["gymleco/products.xlsx", "gymleco/product_details.xlsx", "gymleco/products.xml"]:
            if os.path.exists(filename):
                file_size = os.path.getsize(filename) / 1024  # Size in KB
                generated_files.append(f"  📄 {filename} ({file_size:.1f} KB)")

        if generated_files:
            logging.info("Generated files:")
            for file_info in generated_files:
                logging.info(file_info)

        sys.exit(0)
    else:
        error_msg = f"One or more scrapers failed!\nProducts scraper: {'✅' if success_products else '❌'}\nDetails scraper: {'✅' if success_details else '❌'}"
        logging.error(f"❌ {error_msg}")
        send_error_notification(error_msg, "Final Summary")
        sys.exit(1)


if __name__ == "__main__":
    try:
        main()
    except KeyboardInterrupt:
        logging.info("\n⚠️  Process interrupted by user")
        sys.exit(1)
    except Exception as e:
        error_msg = f"Fatal error in main execution: {str(e)}"
        logging.error(f"❌ {error_msg}")
        send_error_notification(error_msg, "Main Execution")
        sys.exit(1)