# -*- coding: utf-8 -*-
from datetime import datetime
import os
import argparse
from log_parser import LogParser
import json
import re


def find_crash_directories(base_dir="/var/crash"):
    if not os.path.exists(base_dir) or not os.path.isdir(base_dir):
        return []
    directories = []
    for entry in os.listdir(base_dir):
        if entry == "." or entry == "..":
            continue

        entry_path = os.path.join(base_dir, entry)
        if os.path.isdir(entry_path):
            directories.append(entry_path)
    return directories


def diagnose_dmesg(file):
    lg = LogParser()
    detail = lg.parse_file(file)
    return detail.to_dict()


def check_for_vmcore_dmesg(directory):
    vmcore_dmesg_path = os.path.join(directory, "vmcore-dmesg.txt")
    if os.path.exists(vmcore_dmesg_path) and os.path.isfile(vmcore_dmesg_path):
        return diagnose_dmesg(vmcore_dmesg_path)
    return None


def get_core_time(fname):
    pat = re.compile(r"(\d+)-(\d+)-(\d+)-(\d+):(\d+):(\d+)")
    m = pat.search(fname)
    return m.group(0) if m else None


def range_check(start, end, core_time):
    core_time = datetime.strptime(core_time, "%Y-%m-%d-%H:%M:%S")
    start_time = datetime.strptime(start, "%Y-%m-%d %H:%M:%S") if start else None
    end_time = datetime.strptime(end, "%Y-%m-%d %H:%M:%S") if end else None
    if start_time and core_time < start_time:
        return False
    if end_time and core_time > end_time:
        return False
    return True


def parse_args():
    parser = argparse.ArgumentParser(description="crash dmesg diagnose tool")
    parser.add_argument(
        "-d",
        "--crashdir",
        type=str,
        required=False,
        default="",
        help="crash directory",
    )
    parser.add_argument(
        "-f",
        "--file",
        type=str,
        required=False,
        default="",
        help="parse dmesg file",
    )
    parser.add_argument(
        "-s",
        "--starttime",
        type=str,
        required=False,
        default="",
        help="start time (format: YYYY-MM-DD HH:MM:SS)",
    )
    parser.add_argument(
        "-e",
        "--endtime",
        type=str,
        required=False,
        default="",
        help="end time (format: YYYY-MM-DD HH:MM:SS)",
    )
    return parser.parse_args()


def process_result(res, crash_list, coredir=None, core_time=None):
    if res:
        res["core_time"] = core_time
        crash_list.append(
            {
                "crashdir": coredir,
                "detail": res,
            }
        )


def main(args):
    crash_list = []
    if args.crashdir:
        res = check_for_vmcore_dmesg(args.crashdir)
        process_result(res, crash_list)
    elif args.file:
        res = diagnose_dmesg(args.file)
        process_result(res, crash_list)
    else:
        dirs = find_crash_directories()
        for coredir in dirs:
            core_time = get_core_time(coredir)
            if not core_time:
                continue
            if range_check(args.starttime, args.endtime, core_time):
                res = check_for_vmcore_dmesg(coredir)
                process_result(res, crash_list, core_time)

    crash_list.sort(
        key=lambda x: (
            datetime.strptime(x["detail"]["core_time"], "%Y-%m-%d-%H:%M:%S")
            if x["detail"]["core_time"]
            else datetime.now()
        ),
        reverse=True,
    )
    print(json.dumps(crash_list, indent=4, ensure_ascii=False))


if __name__ == "__main__":
    args = parse_args()
    main(args)
