import datetime
import gitlab
import smtplib
import shutil
import os
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
import subprocess
import requests
from dotenv import load_dotenv


def check_binaries():
    required_binaries = ['df', 'gitlab-ctl']
    missing_binaries = [binary for binary in required_binaries if not shutil.which(binary)]

    if missing_binaries:
        print(f"Error: The following binaries are missing: {', '.join(missing_binaries)}")
        print("Please ensure they are installed and available in the system's PATH.")
        exit(1)

def load_api_token():
    load_dotenv()  # Load environment variables from .env file
    api_token = os.getenv('GITLAB_API_TOKEN')

    if not api_token:
        print("Error: Gitlab API token not found in .env file.")
        exit(1)

    confluence_token = os.getenv('CONFLUENCE_API_TOKEN')

    if not confluence_token:
        print("Error: Confluence API token not found in .env file.")
        exit(1)

    gitlab_url = os.getenv('GITLAB_URL')

    if not gitlab_url:
        print("Error: Gitlab URL not found in .env file.")
        exit(1)

    sender_mail = os.getenv('SENDER_MAIL')

    if not sender_mail:
        print("Error: Sender email address not found in .env file.")
        exit(1)

    recipient_email = os.getenv('RECIPIENT_MAIL')

    if not recipient_email:
        print("Error: Recipient email address not found in .env file.")
        exit(1)

    return api_token, confluence_token, gitlab_url, sender_mail, recipient_email

def get_disk_space():
    # Run the df command to get disk space information
    result = subprocess.run(['df', '-h'], stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True)


    # Extract the output and parse the relevant information
    output_lines = result.stdout.strip().split('\n')
   
    # Find the line containing '/data'
    data_line = None
    for line in output_lines:
        if '/data' in line:
            data_line = line
            break

    if data_line is None:
        print("Error: /data not found in the 'df' output.")
        return None


    data_info = data_line.split()

    # Extract the available space (Avail) and percentage (Use%) for /data
    free_space_on_data = data_info[3]
    data_percentage = data_info[4]

    return f"{free_space_on_data} ({data_percentage})"

def get_total_commits_last_month(gl):
    # Calculate the date range for the last month
    current_date = datetime.datetime.now()
    last_month_start = (current_date.replace(day=1) - datetime.timedelta(days=1)).replace(day=1)
    last_month_end = current_date.replace(day=1) - datetime.timedelta(days=1)

    # Get the total commits last month
    total_commits_last_month = 0
    projects = gl.projects.list(all=True)
    for project in projects:
        try:
            commits = project.commits.list(since=last_month_start, until=last_month_end)
            total_commits_last_month += len(commits)
        except gitlab.exceptions.GitlabListError as e:
            if e.response_code == 404:
                # Repository not found for the project
                print(f"Warning: Repository not found for project '{project.name}'")
            else:
                # Other GitLab API error
                print(f"Error: GitLab API error for project '{project.name}': {e}")

    return total_commits_last_month


def get_gitlab_version():
    # Run 'gitlab-ctl' command to get GitLab version
    result = subprocess.run(['grep', 'gitlab-ee', '/opt/gitlab/version-manifest.txt'],stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True)

    # Extract GitLab version from the output
    gitlab_version = result.stdout.strip()

    return gitlab_version

def get_gitlab_info(api_token):
    # Replace 'YOUR_GITLAB_URL' and 'YOUR_PRIVATE_TOKEN' with your GitLab URL and private token
    print("Auth against "+gitlab_url)   
    gl = gitlab.Gitlab(gitlab_url, api_token)
    gl.auth()
    print("Auth successful")

    # Get the number of projects
    projects = gl.projects.list(all=True)
    num_projects = len(projects)
    print(f"Number of projects: {num_projects}")

    # Get the number of users
    users = gl.users.list(all=True)
    num_users = len(users)
    print(f"Number of users: {num_users}")


    # Get a list of admin users
    admin_users = [user for user in users if hasattr(user, 'is_admin') and user.is_admin]
    admin_users_list = [user.name for user in admin_users]
    print(f"Number of Admin-Users: {len(admin_users_list)}")


    # Get free space on disk
    free_space_on_disk = get_disk_space()
    print(f"Free space on disk: {free_space_on_disk}")

    # Get the total commits last month
    total_commits_last_month = get_total_commits_last_month(gl)
    print(f"Total commits last month: {total_commits_last_month}")



    # Get GitLab version
    gitlab_version = get_gitlab_version()
    print(f"GitLab version: {gitlab_version}")


    return num_projects, num_users, admin_users_list, free_space_on_disk, total_commits_last_month, gitlab_version

def send_email(sender_email, recipient_email, subject, body):
    # Create the email body in HTML format
    msg = MIMEMultipart('alternative')
    msg['From'] = sender_email
    msg['To'] = recipient_email
    msg['Subject'] = subject

    # Create a nice HTML table for the report
    html_table = f'''
    <html>
        <head></head>
        <body>
            <h2>Monthly GitLab Report - {datetime.datetime.now().strftime('%B %Y')}</h2>
            <p>Version: {body['gitlab_version']}</p>
            <table border="1" cellpadding="5" style="border-collapse: collapse; width: 100%;">
                <tr>
                    <th>Metrics</th>
                    <th>Values</th>
                </tr>
                <tr>
                    <td>Number of Projects</td>
                    <td>{body['num_projects']}</td>
                </tr>
                <tr>
                    <td>Number of Users</td>
                    <td>{body['num_users']}</td>
                </tr>
                <tr>
                    <td>List of Admin Users</td>
                    <td>
                        <ul>
                            {"".join(f"<li>{admin_user}</li>" for admin_user in body['admin_users_list'])}
                        </ul>
                    </td>
                </tr>
                <tr>
                    <td>Free Space on Disk</td>
                    <td>{body['free_space_on_disk']}</td>
                </tr>
                <tr>
                    <td>Total Commits last Month</td>
                    <td>{body['total_commits_last_month']}</td>
                </tr>
            </table>
        </body>
    </html>
    '''

    # Attach the HTML content to the email
    msg.attach(MIMEText(html_table, 'html'))

    with smtplib.SMTP('localhost') as server:
        server.sendmail(sender_email, recipient_email, msg.as_string())

def create_blog_post(confluence_url, api_token, blog_post_content):
    headers = {
        "Authorization": f"Bearer {api_token}",
        "Content-Type": "application/json"
    }

    blog_post_content = {
        "type": "blogpost",
        "title": "Monthly GitLab Report",
        "space": {
            "key": "SPACE_KEY"  # Replace with the key of the space where you want to create the blog post
        },
        "body": {
            "storage": {
                "value": "<h2>Monthly GitLab Report</h2><p>This is your blog post content in HTML format.</p>",
                "representation": "storage"
            }
        }
    }


    # Make a POST request to create the blog post
    response = requests.post(
        f"{confluence_url}/rest/api/content",
        headers=headers,
        json=blog_post_content
    )

    if response.status_code == 200:
        print("Blog post created successfully!")
        return response.json().get("id")
    else:
        print("Failed to create the blog post.")
        print(f"Status code: {response.status_code}")
        print(f"Response: {response.text}")
        return None

# Check if required binaries are available
check_binaries()

api_token, confluence_token, gitlab_url, sender_email, recipient_email = load_api_token()


subject = '[gitlab.ard.de] Monthly Report - {month} {year}'.format(month=datetime.datetime.now().strftime('%B'), year=datetime.datetime.now().strftime('%Y'))

# Get GitLab information
num_projects, num_users, admin_users_list, free_space_on_disk, total_commits_last_month, gitlab_version = get_gitlab_info(api_token)

# Compose the email body as a dictionary
email_body = {
    'num_projects': num_projects,
    'num_users': num_users,
    'admin_users_list': admin_users_list,
    'free_space_on_disk': free_space_on_disk,
    'total_commits_last_month': total_commits_last_month,
    'gitlab_version': gitlab_version
}

# Send the email
send_email(sender_email, recipient_email, subject, email_body)

# create blog post
# blog_post_id = create_blog_post(confluence_url, api_token, email_body)