import configparser
import hashlib
import re
import shutil
import subprocess
import tempfile
from pathlib import Path

# Load configuration from config.ini
config = configparser.ConfigParser()
config.read('config.ini')

# Retrieve credentials
USERNAME = config.get('git', 'username')
PASSWORD = config.get('git', 'password')

# Configuration
REPO_URL = f'https://{USERNAME}:{PASSWORD}@git.sbdevelopment.tech/SBDevelopment/docs'
REPO_DIR = tempfile.mkdtemp()
SETUP_FILE_PATH = 'vehiclesplus/setup.md'
RESOURCE_PACK_DIR = '../../ResourcePacks/Examples-v2'
VERSIONS_FILE_PATH = 'versions_v2.txt'
BRANCH = 'main'
BASE_URL = 'https://git.sbdevelopment.tech/SBDevelopment/VehiclesPlus/raw/branch/master/ResourcePacks/Examples-v2/'

def run_command(command):
    """Run a shell command and return its output."""
    try:
        result = subprocess.run(command, shell=True, capture_output=True, text=True)
        result.check_returncode()
        return result.stdout
    except subprocess.CalledProcessError as e:
        print(f"Error executing command: {command}")
        print(f"Return code: {e.returncode}")
        print(f"Standard output: {e.stdout}")
        print(f"Standard error: {e.stderr}")
        raise

def clone_repo():
    """Clone the repository into the temp directory."""
    print(f"Cloning repository from {REPO_URL} into {REPO_DIR}")
    run_command(f'git clone {REPO_URL} {REPO_DIR}')

def find_setup_file():
    """Find and return the path of the setup.md file."""
    setup_file = Path(REPO_DIR) / SETUP_FILE_PATH
    if not setup_file.exists():
        raise FileNotFoundError(f"{setup_file} does not exist.")
    return setup_file

def list_zip_files():
    """List all ZIP files in the ResourcePacks/Examples-v2 directory."""
    resource_pack_path = Path(RESOURCE_PACK_DIR)
    if not resource_pack_path.exists():
        raise FileNotFoundError(f"{resource_pack_path} does not exist.")

    zip_files = list(resource_pack_path.glob('VPExample-v2-*.zip'))
    print(f"Found ZIP files: {zip_files}")
    return zip_files

def extract_version_info(zip_filename):
    """Extract version information from the zip filename."""
    pattern = re.compile(r'^VPExample-v2-(\d+\.\d+(?:\.\d+)?)(?:-(\d+\.\d+(?:\.\d+)?))?\.zip$')
    match = pattern.match(zip_filename.name)
    if match:
        if match.group(2):  # Handle version ranges
            print(f"Version range detected: {match.group(1)} - {match.group(2)}")
            return f"{match.group(1)}-{match.group(2)}"
        else:  # Single version
            print(f"Version detected: {match.group(1)}")
            return match.group(1)

def calculate_sha1(file_path):
    """Calculate SHA1 hash of the given file."""
    sha1 = hashlib.sha1()
    with open(file_path, 'rb') as f:
        while chunk := f.read(8192):
            sha1.update(chunk)
    return sha1.hexdigest()

def read_versions_file():
    """Read the versions_v2.txt file and return a list of (order, version) tuples."""
    versions = []
    with open(VERSIONS_FILE_PATH, 'r') as file:
        for line in file:
            parts = line.strip().split('#')
            if len(parts) == 2:
                order = int(parts[0])
                version_range = parts[1]
                versions.append((order, version_range))
    # Sort by order
    versions.sort()
    return [version for _, version in versions]

def update_setup_file(setup_file_path, zip_files):
    """Update the setup.md file with correct paths and SHA1 checksums."""
    with open(setup_file_path, 'r') as file:
        lines = file.readlines()

    table_header_found = False
    table_alignment_found = False
    table_start_index = None
    table_end_index = None

    # Identify the table header and alignment rows
    for index, line in enumerate(lines):
        if line.strip() == '| Version | Download | SHA1 Hash |':
            table_header_found = True
            table_start_index = index
        elif table_header_found and line.strip() == '|:---:|:---:|---|':
            table_alignment_found = True
        elif table_header_found and table_alignment_found and line.strip() == '':
            table_end_index = index
            break

    if table_start_index is not None and table_end_index is not None:
        # Prepare to insert new rows
        new_lines = lines[:table_start_index + 2]  # Keep header and alignment lines

        # Read the versions file to determine the order
        version_order = read_versions_file()

        # Create a dictionary for quick lookup
        zip_file_dict = {}
        for zip_file in zip_files:
            version = extract_version_info(zip_file)
            if version:
                zip_file_dict[version] = zip_file

        print(f"ZIP file dictionary: {zip_file_dict}")

        # Insert new rows in the correct order
        new_rows = []
        for version in version_order:
            zip_file = zip_file_dict.get(version)
            print(f"Checking version: {version}")
            if zip_file:
                print (f"Found ZIP file: {zip_file}")
                file_url = f"{BASE_URL}{zip_file.name}"
                sha1_checksum = calculate_sha1(zip_file)
                new_row = f"| {version} | [Click here]({file_url}) | `{sha1_checksum}` |\n"
                new_rows.append(new_row)

        if new_rows:
            # Only update the file if new rows were added
            print(f"Adding rows: {new_rows}")
            new_lines.extend(new_rows)
            new_lines.extend(lines[table_end_index:])
        else:
            print("No new rows to add.")

    with open(setup_file_path, 'w') as file:
        file.writelines(new_lines)

def commit_and_push_changes():
    """Commit and push changes to the repository."""
    print(f"Committing and pushing changes to {REPO_DIR}")
    run_command(f'cd {REPO_DIR} && git add {SETUP_FILE_PATH}')
    result = run_command(f'cd {REPO_DIR} && git commit -m "Update vehicle setup file with correct paths and SHA1 checksums"')
    if 'nothing to commit' in result:
        print("No changes detected.")
    else:
        run_command(f'cd {REPO_DIR} && git push origin {BRANCH}')

def cleanup():
    """Remove the temp directory."""
    shutil.rmtree(REPO_DIR)

def main():
    try:
        clone_repo()
        setup_file_path = find_setup_file()
        zip_files = list_zip_files()
        update_setup_file(setup_file_path, zip_files)
        commit_and_push_changes()
    finally:
        cleanup()

if __name__ == "__main__":
    main()