
import PySimpleGUI as sg
import pandas as pd
import openpyxl
from openpyxl.styles import Font, Alignment, Border, Side, PatternFill
from datetime import datetime, timedelta
import time
import os
from pathlib import Path
import logging
import sys


def select_file(names, mode='single'):
    sg.theme('Dark Blue 3')
    layout = [[sg.Text('Choose files ')]]

    if mode == 'single':
        for name in names:
            layout.append([sg.Text(name + ": ", size=(15, 1),),
                           sg.InputText(), sg.FileBrowse()])
    elif mode == 'multi':
        for name in names:
            layout.append([sg.Text(name + ": ", size=(15, 1),),
                           sg.InputText(key=f'{name}'), sg.FilesBrowse()])

    layout.append([sg.Submit(), sg.Cancel()])

    window = sg.Window('File Selector', layout)
    event, values = window.read()
    window.close()

    if event == 'Submit':
        if mode == 'single':
            file_paths = [values[i] for i in range(len(names))]
        elif mode == 'multi':
            file_paths = [values[f'{name}'].split(';') for name in names]
        return file_paths
    elif event == 'Cancel':
        print('File selection cancelled.')
        sys.exit()
    elif event == sg.WIN_CLOSED:
        print('File selection closed.')
        sys.exit()
    else:
        return None


def read_file(filepath):
    # Determine file type based on extension
    if filepath.lower().endswith(('.txt', '.csv', '.xlsx', '.xls')):
        if filepath.lower().endswith('.txt'):
            df = pd.read_csv(filepath, sep='	', low_memory=False)
        elif filepath.lower().endswith('.csv'):
            df = pd.read_csv(filepath, low_memory=False)
        elif filepath.lower().endswith('.xlsx'):
            df = pd.read_excel(filepath, engine='openpyxl')
        elif filepath.lower().endswith('.xls'):
            df = pd.read_excel(filepath, engine='xlrd')
        return df
    else:
        raise ValueError("Unsupported file format")


def read_logfile(filepath):
    if filepath.lower().endswith('.log'):
        with open(filepath, 'r') as f:
            lines = f.readlines()

        # create a dataframe from the list of strings
        df_log = pd.DataFrame(lines, columns=['log'])
        return df_log
    else:
        raise ValueError("Unsupported file format")


def save_file(df_result, file_name, mode="Result"):
    # Generate a timestamp for the current date and time
    date_time = datetime.now().strftime("%d%m%y_%H%M%S")

    # Append the timestamp to the filename to make it unique
    file_name = f'{file_name} {date_time}.xlsx'

    if mode == "Result":
        # Create the result directory if it doesn't exist
        Path("Result").mkdir(exist_ok=True)

        # Change the current working directory to the result directory
        os.chdir("Result")

    # Save the DataFrame to an Excel file without the index
    df_result.to_excel(file_name, index=False)

    # Load the Excel spreadsheet
    wb = openpyxl.load_workbook(file_name)
    ws = wb.active

    # Set the font and alignment styles for all cells
    font = Font(name='Calibri', size=11)
    alignment = Alignment(horizontal='center',
                          vertical='center')

    # Add borders to all cells
    border = Border(left=Side(border_style='thin', color='000000'),
                    right=Side(border_style='thin', color='000000'),
                    top=Side(border_style='thin', color='000000'),
                    bottom=Side(border_style='thin', color='000000'))

    # Set the background color and font and alignment styles for the first row
    fill = PatternFill(start_color='FFC000',
                       end_color='FFC000', fill_type='solid')
    font_first_row = Font(name='Calibri', size=11, bold=True)
    alignment_first_row = Alignment(
        horizontal='center', vertical='center', wrap_text=True)

    # Set all columns to the same width as the original file
    for i, column in enumerate(ws.columns):
        ws.column_dimensions[column[0].column_letter].width = 15

    # Format all cells in the worksheet
    for row in ws.rows:
        for cell in row:
            if cell.row == 1:
                # Format the first row cells
                cell.font = font_first_row
                cell.alignment = alignment_first_row
                cell.border = border
                cell.fill = fill
            else:
                # Format all other cells
                cell.font = font
                cell.alignment = alignment
                cell.border = border

    # Save the modified Excel spreadsheet
    wb.save(file_name)
    print('Finish create excel file!')

    # Return the full file path of the saved file
    return os.path.join(os.getcwd(), file_name)


def format_excel(file_name):
    # Load the Excel spreadsheet
    wb = openpyxl.load_workbook(file_name)
    ws = wb.active

    # Set the font and alignment styles for all cells
    font = Font(name='Calibri', size=11)
    alignment = Alignment(horizontal='center',
                          vertical='center')

    # Add borders to all cells
    border = Border(left=Side(border_style='thin', color='000000'),
                    right=Side(border_style='thin', color='000000'),
                    top=Side(border_style='thin', color='000000'),
                    bottom=Side(border_style='thin', color='000000'))

    # Set the background color and font and alignment styles for the first row
    fill = PatternFill(start_color='FFC000',
                       end_color='FFC000', fill_type='solid')
    font_first_row = Font(name='Calibri', size=11, bold=True)
    alignment_first_row = Alignment(
        horizontal='center', vertical='center', wrap_text=True)

    # Set all columns to the same width as the original file
    for i, column in enumerate(ws.columns):
        ws.column_dimensions[column[0].column_letter].width = 15

    # Format all cells in the worksheet
    for row in ws.rows:
        for cell in row:
            if cell.row == 1:
                # Format the first row cells
                cell.font = font_first_row
                cell.alignment = alignment_first_row
                cell.border = border
                cell.fill = fill
            else:
                # Format all other cells
                cell.font = font
                cell.alignment = alignment
                cell.border = border

    # Save the modified Excel spreadsheet
    wb.save(file_name)
    print('Finish create excel file!')


def check_license(start_date_str, duration_days):
    start_date = datetime.fromisoformat(start_date_str)
    end_date = start_date + timedelta(days=duration_days)
    now_date = datetime.now()
    time_compare = end_date.timestamp() - now_date.timestamp()
    days_remaining = int(time_compare / 86400)   # convert seconds to days
    if days_remaining < 0:
        print(
            'Your program license has been expired, please contact to provider for more information!')
        return False
    elif days_remaining == 0 or days_remaining == 1:
        print(f'License: {days_remaining} day')
        return True
    elif days_remaining <= 30 and days_remaining > 1:
        print('Lic = True')
        print(f'License: {days_remaining} days')
        return True
    else:
        print('Lic = True')
        return True


def popup_finish(program_running_time, result_path):
    message = '        Finish!' + '            ' + '\n' +\
        '        Program running time: ' + program_running_time + '            ' + '\n' +\
        '        Result: ' + result_path + '\n' +\
        '        Copyright: VinhVH      '
    sg.popup_auto_close(
        message, title='Program running result', auto_close_duration=20)


def popup_error():
    # Create the result directory if it doesn't exist
    Path("Logfile").mkdir(exist_ok=True)
    # Change the current working directory to the Logfile directory
    os.chdir("Logfile")
    date_time = datetime.now().strftime("%d%m%y_%H%M%S")
    logfile = f'Error logfile {date_time}.log'

    # Configure the logging module
    logging.basicConfig(filename=logfile, level=logging.ERROR)

    try:
        # Your code that may raise an exception
        raise Exception("Something went wrong")
    except Exception as e:
        # Log the exception to the file
        logging.exception("An exception was thrown: %s", str(e))
        # Print the exception to the terminal
        print("An exception was thrown: ", str(e))
        # Print the exception traceback to the terminal
        exc_type, exc_value, exc_traceback = sys.exc_info()
        traceback_details = {
            'filename': exc_traceback.tb_frame.f_code.co_filename,
            'lineno': exc_traceback.tb_lineno,
            'name': exc_traceback.tb_frame.f_code.co_name,
            'type': exc_type.__name__,
            'message': str(exc_value)
        }
        for key, value in traceback_details.items():
            print(f"{key}: {value}")

    message = f'        Error \n        Bye bye!'
    sg.popup_auto_close(message, title='Notice',
                        auto_close_duration=20, background_color='red')
    time.sleep(10)


def start():
    st_time = time.time()
    start_time = datetime.now()
    print('Program is running...')
    print('Start running time:', start_time.strftime("%d/%m/%Y, %H:%M:%S"))
    return st_time


def end(st_time, result_path):
    end_time = time.time()
    finish_time = datetime.now()
    print('End running time:', finish_time.strftime("%d/%m/%Y, %H:%M:%S"))
    running_time = end_time - st_time
    program_running_time = f"{int(running_time//60)}'" + \
        f'{int(running_time%60)}s'
    print('Program running time:', program_running_time)
    print('Mission completed!')
    message = f'        Finish!\n        Program running time: {program_running_time}\n        Result path: {result_path}\n        Copyright: VinhVH'
    sg.popup_auto_close(
        message, title='Running result', auto_close_duration=20)
