#!/usr/bin/env python
# -*- coding: utf-8 -*-

import argparse
import logging
import re
import subprocess
import pandoraPlugintools as ppt
import sys
import os
from datetime import datetime,timedelta
from pathlib import Path
import base64

def setup_logging(verbose=False):
    level = logging.DEBUG if verbose else logging.INFO
    logging.basicConfig(
        level = level,
        format = "%(asctime)s [%(levelname)s] %(message)s",
        datefmt = "%H:%M:%S"
    )

def journal_command(last_execution_time):
    try:
        command = ['journalctl', '--since', last_execution_time, '--no-pager']

        process = subprocess.run(
            command,
            capture_output=True,
            text=True,
            check=True
        )
        log_output  = process.stdout
        return log_output

    except FileNotFoundError:
        logging.error("Error: 'journalctl' command not found. Ensure systemd is installed and accessible in the PATH.")
    except subprocess.CalledProcessError as e:
        logging.error(f"Error executing journalctl: {e}")
        logging.error(f"Stderr: {e.stderr}")
    except Exception as e:
        logging.error(f"An unexpected error occurred: {e}")

    sys.exit(1)

def save_execution_time(file_path: Path):
    try:
        now_str = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
        with open(file_path, 'w', encoding='utf-8') as f:
            f.write(now_str)
        logging.debug(f"Saved execution time: {now_str} -> {file_path}")
    except Exception as e:
        logging.error(f"Failed to save execution time: {e}")

if __name__ == "__main__":
    parser = argparse.ArgumentParser(description="View later the programs description",
    formatter_class=argparse.RawTextHelpFormatter)
    parser.add_argument('-in', '--regex_in', type=str, default=False, help='Allows only log lines that match a regular expression to be included. This parameter takes precedence over --regex_out (if used, the exclusion filter is ignored). Example -in [a-zA-Z0-9]+')
    parser.add_argument('-out', '--regex_out', type=str, default=False, help='Allows you to exclude log lines that match a regular expression. Only applies if --regex_in has not been defined. Example -out [a-zA-Z0-9]+')
    parser.add_argument('-s', '--source', type=str, default="Journalctl", help='Source event name')
    parser.add_argument("--verbose", "-v", action = "store_true", help = "Enable detailed output")
    args = parser.parse_args()

    setup_logging(verbose = args.verbose)

    if args.regex_in: args.regex_out = False # regex_in priority

    try:
        if args.regex_in: re.compile(args.regex_in)
        if args.regex_out: re.compile(args.regex_out)
    except re.error as e:
        logging.error(f"Invalid regex: {e}")
        sys.exit(1)


    if not os.access("/tmp", os.W_OK):
        logging.error("No write permissions for /tmp")
        sys.exit(1)

    last_file = Path("/tmp/journalctl_logs.index")
    last_time = False
    
    if last_file.exists():
        
        try:
            with open(last_file, 'r', encoding="utf-8") as file:
                last_time = file.readline().strip()
                try:
                    datetime.strptime(last_time, "%Y-%m-%d %H:%M:%S")
                except ValueError:
                    last_time = False
        except Exception as e:
            last_time = False

    if not last_time:
        last_time = (datetime.now() - timedelta(minutes=5)).strftime("%Y-%m-%d %H:%M:%S")

    
    logs = journal_command(last_time)
    if not logs or not logs.strip():
        logging.info("No new logs.")
        sys.exit(0)

    try:
        for line in logs.strip().split('\n'):
            if args.regex_in and not re.search(args.regex_in, line): continue
            if args.regex_out and re.search(args.regex_out, line): continue
            if isinstance(line, str):line = line.encode()
            value = base64.b64encode(line).decode("utf-8")
            module = {'source': args.source, 'value': value}
            ppt.print_log_module(module, encoding="base64", print_flag=True)
    except KeyboardInterrupt:
        logging.info("Execution interrupted.")
        sys.exit(0)
    except Exception as e:
        logging.error(f"Error processing logs: {e}")
        sys.exit(1)

    save_execution_time(last_file)