import imaplib
import email
import re
import os
import datetime
from reportlab.lib.pagesizes import letter
from reportlab.pdfgen import canvas
from argparse import ArgumentParser


def extract_text_from_email(email_message):
    """Extract the text from an email message.
    This function extracts the text from an email message by recursively
    searching through the email parts.
    """
    text = ""
    for part in email_message.walk():
        if part.get_content_type() == "text/plain":
            text += part.get_payload()
    return text


def extract_client_name(text):
    """Extract the client name from the email text.
    This function extracts the client name from the email text by searching
    for a pattern that looks like "Bill To: Client Name".
    """
    pattern = r"Bill To: (.+)"
    match = re.search(pattern, text, re.IGNORECASE)
    if match:
        return match.group(1)
    else:
        return None


def create_client_folder(output_dir, client_name):
    """Create a folder for the client if it does not exist.
    """
    client_dir = os.path.join(output_dir, client_name)
    if not os.path.exists(client_dir):
        os.mkdir(client_dir)
    return client_dir


def save_attachment(attachment, output_filename):
    """Save an email attachment to a file.
    """
    with open(output_filename, "wb") as f:
        f.write(attachment.get_payload(decode=True))


def process_email(email_message, keywords, output_dir):
    """Process an email message and save any invoices to the output directory.
    """
    text = extract_text_from_email(email_message)
    client_name = extract_client_name(text)
    if client_name:
        client_dir = create_client_folder(output_dir, client_name)
        for part in email_message.walk():
            filename = part.get_filename()
            if filename and any(keyword in filename.lower() or keyword in text.lower() for keyword in keywords):
                output_filename = os.path.join(client_dir, filename)
                save_attachment(part, output_filename)


def search_emails(server, username, password, keywords):
    """Search for emails with the specified keywords.
    This function connects to the email server and searches for emails with
    the specified keywords in the subject line or body of the email. It then
    processes any emails with invoices.
    """
    imap = imaplib.IMAP4_SSL(server)
    imap.login(username, password)
    imap.select("INBOX")
    # Search for emails with the specified keywords
    for keyword in keywords:
        result, data = imap.search(None, f'(OR SUBJECT "{keyword}" BODY "{keyword}")')
        if result == "OK":
            for email_id in data[0].split():
                result, data = imap.fetch(email_id, "(RFC822)")
                if result == "OK":
                    email_message = email.message_from_bytes(data[0][1])
                    process_email(email_message, keywords, output_dir)
    imap.logout()


def generate_report(output_dir):
    """Generate a PDF report of the invoices processed.
    This function generates a PDF report that lists the number of invoices
    processed and the number of invoices for each client.
    """
    # Get the current date and time
    now = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
    # Get a list of all client folders in the output directory
    clients = os.listdir(output_dir)
    # Create a new PDF file
    pdf_filename = "report.pdf"
    pdf = canvas.Canvas(pdf_filename, pagesize=letter)
    # Add a title to the first page of the PDF
    pdf.setFont("Helvetica-Bold", 16)
    pdf.drawString(100, 700, "Invoice Report")
    pdf.setFont("Helvetica", 12)
    pdf.drawString(100, 670, f"Generated on: {now}")
    pdf.drawString(100, 640, f"Number of invoices processed: {len(clients)}")
    # Add a table of clients and the number of invoices for each client
    y = 600
    for client in clients:
        invoices = os.listdir(os.path.join(output_dir, client))
        pdf.drawString(100, y, f"{client}: {len(invoices)} invoices")
        y -= 20
    # Save the PDF file
    pdf.save()
    # Print the report to the console
    print(f"Report generated on {now}")
    print(f"Number of invoices processed: {len(clients)}")
    for client in clients:
        invoices = os.listdir(os.path.join(output_dir, client))
        print(f"{client}: {len(invoices)} invoices")