import json
import smtplib
import os
import datetime
import requests
import pandas as pd
from email.message import EmailMessage
from openpyxl import load_workbook
from openpyxl.utils import get_column_letter
from openpyxl.styles import Font, Alignment, PatternFill, Border, Side


# --- Config and color map ---
color_map = {
    "all_ok": "4CAF50",  #Green present
    "act4_true": "009688", # teal Regularization is accepted
    "act1_nullOut": "FFC107",  #Amber Check out pending
    "act2": "2196F3", # Bule Regularization pending
    "act5": "B71C1C", #Dark Red Regularization rejected
    "all_null": "F6635C", #Red Absent
    "sunday":"FF0000"
}

# Add Legend sheet to the workbook
legend_data = {
    "Color Description": [
        "Present (All Ok)",
        "Regularization Accepted",
        "Check-out Pending",
        "Regularization Pending",
        "Regularization Rejected",
        "Absent",
        "Sundays"
    ],
    "Hex Color": [
        color_map["all_ok"],
        color_map["act4_true"],
        color_map["act1_nullOut"],
        color_map["act2"],
        color_map["act5"],
        color_map["all_null"],
        color_map["sunday"]
    ]
}

def login_api():
    payload = {"username": API_USERNAME, "password": API_PASSWORD}
    headers = {"Content-Type": "application/json"}
    try:
        response = requests.post(f"{BASE_URL}/auth/login", json=payload, headers=headers)
        response.raise_for_status()
        data = response.json()["data"]
        jwt = data["token"]
        print("API login successful.")
        return jwt
    except Exception as e:
        print(f"Login API error: {e}")
        return None

def select_tenant(jwt):
    headers = {"Authorization": f"Bearer {jwt}", "Content-Type": "application/json"}
    try:
        response = requests.post(f"{BASE_URL}/auth/select-tenant/{API_TENANT}", headers=headers)
        response.raise_for_status()
        data = response.json()["data"]
        jwt = data["token"]
        print("Tenant selected successful.")
        return jwt
    except Exception as e:
        print(f"Select tenant error: {e}")
        return None

def attendance_report(jwt,is_current_month):
    headers = {"Authorization": f"Bearer {jwt}", "Content-Type": "application/json"}
    response = requests.get(f"{BASE_URL}/report/report-attendance?isCurrentMonth={is_current_month}", headers=headers)
    response.raise_for_status()
    data = response.json()
    projects = data.get('data', [])

    # Get current date and time
    today = datetime.datetime.now()

    if not is_current_month:
        first_day_current_month = today.replace(day=1)
        last_month_last_day = first_day_current_month - datetime.timedelta(days=1)
        month_name = last_month_last_day.strftime("%B")
        year = last_month_last_day.year
    else:
        month_name = today.strftime("%B")
        year = today.year

    excel_file = f"{month_name}-{year}_attendance_report.xlsx"
    writer = pd.ExcelWriter(excel_file, engine="openpyxl")

    # Border style
    thin = Side(border_style="thin", color="000000")
    border = Border(left=thin, right=thin, top=thin, bottom=thin)

    for proj_idx, project in enumerate(projects):
        project_name = project.get('projectName', 'UnknownProject')[:31]  # Sheet name max 31 chars
        attendances = project.get('projectAttendance', [])
        
        # Collect all unique dates in this project
        all_dates = set()
        for user in attendances:
            for att in user.get('attendances', []):
                all_dates.add(att.get('attendanceDate', '').split('T')[0])
        all_dates = sorted(all_dates)
        
        # Prepare rows
        rows = []
        for user in attendances:
            row = {'Name': f"{user.get('firstName','')} {user.get('lastName','')}".strip()}
            date_map = {a.get('attendanceDate', '').split('T')[0]: a for a in user.get('attendances', [])}
            for date in all_dates:
                att = date_map.get(date, {})
                # Store also needed fields for coloring below
                row[f"{date}_checkin"] = ''
                row[f"{date}_checkout"] = ''

                if att.get('checkIn'):
                    # Extract time part only, e.g. "09:30:00"
                    row[f"{date}_checkin"] = att.get('checkIn').split('T')[1]

                if att.get('checkOut'):
                    # Extract time part only
                    row[f"{date}_checkout"] = att.get('checkOut').split('T')[1]
                row[f"{date}_activity"] = att.get('activity', None)
                row[f"{date}_isapproved"] = att.get('isApproved', None)
            row['CheckInCheckOutDone'] = user.get('checkInCheckOutDone', 0)
            row['CheckOutPending'] = user.get('checkOutPending', 0)
            row['CheckInDone'] = user.get('checkInDone', 0)
            row['AbsentAttendance'] = user.get('absentAttendance', 0)
            row['RejectedRegularize'] = user.get('rejectedRegularize', 0)
            rows.append(row)

            legend_df = pd.DataFrame(legend_data)

        # Use the same writer to add sheet after all sheets written
        legend_df.to_excel(writer, sheet_name="Legend", index=False)

        # Access Legend sheet for coloring the color sample cells
        ws_legend = writer.book["Legend"]

        # Assuming data starts from row 2 (header in row 1)
        for row_idx in range(2, 2 + len(legend_data["Color Description"])):
            # Color sample cell: B column (2nd col)
            cell = ws_legend.cell(row=row_idx, column=2)
            hex_color = cell.value
            fill = PatternFill(start_color=hex_color, fill_type="solid")
            cell.fill = fill

            # Optional: bold and center description column
            desc_cell = ws_legend.cell(row=row_idx, column=1)
            desc_cell.font = Font(bold=True)
            desc_cell.alignment = Alignment(horizontal="left", vertical="center")

        # Optionally adjust headers and column width for visual clarity
        for col in [1, 2]:
            ws_legend.column_dimensions[get_column_letter(col)].width = 30

        ws_legend["A1"].font = Font(bold=True)
        ws_legend["B1"].font = Font(bold=True)
        ws_legend["A1"].alignment = ws_legend["B1"].alignment = Alignment(horizontal="center")

        # Columns: Name, checkin/checkout pairs for dates, and summary columns
        columns = ['Name']
        for date in all_dates:
            columns.extend([f"{date}_checkin", f"{date}_checkout"])
        columns.extend(['CheckInCheckOutDone', 'CheckInDone','CheckOutPending', 'AbsentAttendance', 'RejectedRegularize'])
        
        df = pd.DataFrame(rows, columns=columns)

        # Write to sheet
        df.to_excel(writer, sheet_name=project_name, index=False, startrow=2)

        # Post-process sheet using openpyxl
        wb = writer.book
        ws = wb[project_name]

        # Merged header with date and subheaders
        ws["A3"].value = "Name"
        ws["A3"].font = Font(bold=True)
        ws["A3"].alignment = Alignment(horizontal="center", vertical="center")

        col = 2
        for date in all_dates:
            col_letter_1 = get_column_letter(col)
            col_letter_2 = get_column_letter(col + 1)
            ws.merge_cells(f"{col_letter_1}2:{col_letter_2}2")
            ws[f"{col_letter_1}2"].value = pd.to_datetime(date).strftime("%d-%m-%Y")
            ws[f"{col_letter_1}2"].font = Font(bold=True)
            ws[f"{col_letter_1}2"].alignment = Alignment(horizontal="center", vertical="center")
            ws[f"{col_letter_1}3"].value = "Check-in"
            ws[f"{col_letter_2}3"].value = "Check-out"
            ws[f"{col_letter_1}3"].alignment = ws[f"{col_letter_2}3"].alignment = Alignment(horizontal="center")
            col += 2

        # Add headers for summary columns
        summary_headers = ['CheckIn-CheckOut Done', 'CheckIn Done', 'CheckOut Pending', 'Absent Attendance', 'Rejected Regularize']
        summary_start_col = col
        for i, header in enumerate(summary_headers):
            col_letter = get_column_letter(summary_start_col + i)
            ws.merge_cells(f"{col_letter}2:{col_letter}3")
            ws[f"{col_letter}2"].value = header
            ws[f"{col_letter}2"].font = Font(bold=True)
            ws[f"{col_letter}2"].alignment = Alignment(horizontal="center", vertical="center")

        # Apply borders and coloring
        max_row = ws.max_row
        max_col = ws.max_column

        for row_idx in range(3, max_row + 1):  # Starting from 3 to include header rows
            for col_idx in range(1, max_col + 1):
                cell = ws.cell(row=row_idx, column=col_idx)
                cell.border = border
        
        # Coloring according to rules for check-in/out pairs
        for row_idx, user_row in enumerate(rows, start=4):
            for date_idx, date in enumerate(all_dates):
                checkin_col = 2 + date_idx * 2
                checkout_col = checkin_col + 1
                
                activity = user_row.get(f"{date}_activity")
                isapproved = user_row.get(f"{date}_isapproved")
                c_in = user_row.get(f"{date}_checkin")
                c_out = user_row.get(f"{date}_checkout")

                # --- Sunday RED coloring ---
                dt = datetime.datetime.strptime(date, "%Y-%m-%d")
                if dt.weekday() == 6:  # Sunday
                    fill = PatternFill(start_color="FF0000", fill_type="solid")
                    ws.cell(row=row_idx, column=checkin_col).fill = fill
                    ws.cell(row=row_idx, column=checkout_col).fill = fill
                    continue  # Skip further coloring for this date

                fill_color = None
                if not c_in and not c_out:
                    fill_color = color_map["all_null"]
                elif c_in and c_out and activity == 4 and not bool(isapproved):
                    fill_color = color_map["all_ok"]
                elif activity == 4 and bool(isapproved):
                    fill_color = color_map["act4_true"]
                elif activity == 1 and not c_out:
                    fill_color = color_map["act1_nullOut"]
                elif activity == 2:
                    fill_color = color_map["act2"]
                elif activity == 5:
                    fill_color = color_map["act5"]

                if fill_color:
                    fill = PatternFill(start_color=fill_color, fill_type="solid")
                    ws.cell(row=row_idx, column=checkin_col).fill = fill
                    ws.cell(row=row_idx, column=checkout_col).fill = fill

    writer.close()
    print(f"Excel '{excel_file}' generated with sheets per project, summary columns and conditional coloring.")

    # --- 2. Compose the Email ----
    msg = EmailMessage()
    msg["Subject"] = f"Attendance Report for {month_name}-{year}"
    msg["From"] = SENDER_EMAIL
    msg["To"] = RECIPIENT_EMAILS
    msg.set_content("Please find the attached Excel file.")

    # Add the Excel attachment
    with open(excel_file, "rb") as f:
        file_data = f.read()
        file_name = f.name
    msg.add_attachment(file_data, maintype="application", subtype="vnd.openxmlformats-officedocument.spreadsheetml.sheet", filename=file_name)

    # --- 3. Send the Email ----
    with smtplib.SMTP(SMPTSERVER, PORT) as smtp:
        smtp.ehlo()
        smtp.starttls()
        smtp.ehlo()
        smtp.login(SENDER_EMAIL, SENDER_PASSWORD)
        smtp.send_message(msg)

    # After all operations (e.g., emailing) are done, delete the file
    if os.path.exists(excel_file):
        os.remove(excel_file)
        print(f"Deleted file: {excel_file}")
    else:
        print("File not found, cannot delete.")


# --- Main execution logic ---
if __name__ == "__main__":
    import sys
    
    # Load your real config before calling any API
    GLOBAL_CONFIG_PATH = "config.json"
    try:
        with open(GLOBAL_CONFIG_PATH, "r", encoding="utf-8") as f:
            config = json.load(f)
    except Exception as e:
        print(f"Failed to load config: {e}")
        sys.exit(1)

    API_CONFIG = config.get("API", {})
    BASE_URL = API_CONFIG.get("BASE_URL")
    API_USERNAME = API_CONFIG.get("USERNAME")
    API_PASSWORD = API_CONFIG.get("PASSWORD")
    API_TENANT = API_CONFIG.get("TENANTID")

    SMPT_CONFIG = config.get("SMPT", {})
    SMPTSERVER = SMPT_CONFIG.get("SMPTSERVER")
    PORT = SMPT_CONFIG.get("PORT")
    SENDER_EMAIL = SMPT_CONFIG.get("SENDER_EMAIL")
    SENDER_PASSWORD = SMPT_CONFIG.get("SENDER_PASSWORD")
    RECIPIENT_EMAILS = SMPT_CONFIG.get("RECIPIENT_EMAILS")

    token = login_api()
    if not token:
        print("Login failed, aborting.")
        sys.exit(1)

    jwt_token = select_tenant(token)
    if not jwt_token:
        print("Tenant selection failed, aborting.")
        sys.exit(1)

    attendance_report(jwt_token, False)
