import os
import json

""" This was written almost entirely by Google Gemini 2.5 (apps and code) on 18 Sept. 2025

Google Takeout is accessible from the browser when logged in to your Google account.
It can be set up to export dozens of different types of data. Here we only export "Keep"
data.
After running this, move the generated file to expoweb/handbook/troggle
and git add/commit/push
Philip Sargent
"""
# --- CONFIGURATION ---
# 📌 IMPORTANT: Replace this with the actual path to your Google Keep Takeout folder.
TAKEOUT_DIRECTORY = 'Takeout/Keep' # Example for Linux/macOS
#

def process_keep_files_to_dict(directory_path):
    """
    Scans a directory for Google Keep JSON files, filters for a specific
    label, prints the content, and returns the data as a list of dictionaries.

    Args:
        directory_path (str): The path to the folder containing the JSON files.

    Returns:
        list: A list of dictionaries, where each dictionary represents a note.
    """
    print(f"📁 Processing files in: {directory_path}\n")
    
    # This list will store the dictionary for each matching note
    extracted_notes = []

    if not os.path.isdir(directory_path):
        print(f"❌ Error: Directory not found at '{directory_path}'.")
        print("Please update the TAKEOUT_DIRECTORY variable with the correct path.")
        return extracted_notes

    # Iterate over every file in the specified directory
    for filename in os.listdir(directory_path):
        if filename.endswith('.json'):
            file_path = os.path.join(directory_path, filename)
            
            try:
                with open(file_path, 'r', encoding='utf-8') as f:
                    data = json.load(f)

                # --- Label Check ---
                has_expo_label = False
                if 'labels' in data:
                    if any(label.get('name', '').lower() == 'expo' for label in data['labels']):
                        has_expo_label = True

                if not has_expo_label:
                    continue # Skip this file

                # --- Data Extraction & Storage ---
                
                # Create a dictionary to hold the current note's data
                current_note = {
                    'title': data.get('title') or 'Untitled Note',
                    'source_file': filename,
                    'content_type': None,
                    'color': data.get('color', 'DEFAULT'),
                    'content': None
                }
                
                # As before, print to the console for immediate feedback
                print("-" * 40)
                print(f"✅ Title: {current_note['title']}")

                # Handle text notes
                if 'textContent' in data:
                    content = data['textContent']
                    current_note['content_type'] = 'text'
                    current_note['content'] = content
                    print(content)

                # Handle list notes
                elif 'listContent' in data:
                    current_note['content_type'] = 'list'
                    list_items = []
                    checked_items = []
                    unchecked_items = []
                    # print("Tasks:")
                    for item in data['listContent']:
                        # Create a clean dictionary for the list item
                        item_data = {
                            'text': item.get('text', ''),
                            'is_checked': item.get('isChecked', False)
                        }
                        list_items.append(item_data)
                        if item_data['is_checked']:
                            checked_items.append(item_data)
                        else:
                            unchecked_items.append(item_data)
                        # Print the list item to the console
                        # status = 'x' if item_data['is_checked'] else ' '
                        # print(f"  [{status}] {item_data['text']}")
                    print(f"Tasks: {len(list_items)} of which {len(checked_items)} are done.")
                    current_note['content'] = list_items
                    current_note['unchecked'] = unchecked_items
                
                # Add the completed dictionary for this note to our main list
                extracted_notes.append(current_note)
                
                # print("-" * 40 + "\n")

            except Exception as e:
                print(f"❗️ An unexpected error occurred with file {filename}: {e}")
    
    if not extracted_notes:
        print("No notes with the 'EXPO' label were found in the directory.")
    sorted_notes = sorted(extracted_notes, key=lambda note: len(note['unchecked']))

    return sorted_notes

import html
from datetime import datetime

def write_html_output(notes_data, filename="keep_export.html"):
    """
    Generates an HTML file from the extracted Keep notes data.

    Args:
        notes_data (list): A list of note dictionaries.
        filename (str): The name of the output HTML file.
    """
    
    # These are the standard Google Keep colors.
    color_map = {
            "DEFAULT": "#ffffff",
            "RED": "#f28b82",
            "ORANGE": "#fbbc04",
            "YELLOW": "#fff475",
            "GREEN": "#ccff90",
            "TEAL": "#a7ffeb",
            "BLUE": "#cbf0f8",
            "DARK_BLUE": "#aecbfa",
            "PURPLE": "#d7aefb",
            "PINK": "#fdcfe8",
            "BROWN": "#e6c9a8",
            "GRAY": "#e8eaed",
        }    
        
    # --- HTML Head and CSS Styling ---
    # The CSS is embedded directly in the HTML file for simplicity.
    html_head = f"""
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Google Keep Export</title>
    <style>
        body {{
            font-family: 'Google Sans', Roboto, Arial, sans-serif;
            background-color: #f1f3f4;
            margin: 0;
            padding: 24px;
        }}
        .container {{
            display: grid;
            grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
            gap: 16px;
        }}
        .note-card {{
            background-color: #ffffff;
            border: 1px solid #e0e0e0;
            border-radius: 8px;
            padding: 16px;
            box-shadow: 0 1px 3px rgba(0,0,0,0.12);
            word-wrap: break-word; /* Prevents long text from overflowing */
        }}
        .note-title {{
            font-size: 1.1em;
            font-weight: 500;
            margin: 0 0 12px 0;
        }}
        .note-content p {{
            margin: 0;
            white-space: pre-wrap; /* Respects newlines in text notes */
        }}
        .task-list {{
            list-style: none;
            padding: 0;
            margin: 0;
        }}
        .task-item {{
            display: flex;
            align-items: center;
            margin-bottom: 8px;
        }}
        .task-item input[type="checkbox"] {{
            margin-right: 10px;
        }}
        .completed-item-text {{
            text-decoration: line-through;
            color: #5f6368;
        }}
        .completed-items {{
            margin-top: 16px;
            border-top: 1px solid #e0e0e0;
            padding-top: 12px;
        }}
        .completed-items summary {{
            cursor: pointer;
            font-weight: bold;
            color: #3c4043;
        }}
    </style>
</head>
"""

    # --- HTML Body Generation ---
    html_body_content = ""
    for note in notes_data:
        # Sanitize title to prevent HTML injection issues
        title = html.escape(note['title'])
        
        # Start building the content for this specific note
        note_content_html = ""
        
        # MODIFICATION 2: Get the color and apply it as an inline style
        note_color_name = note.get('color', 'DEFAULT')
        # Safely get the color from the map, falling back to the default white
        bg_color = color_map.get(note_color_name, color_map['DEFAULT'])
        
        # Handle text notes
        if note['content_type'] == 'text':
            # Sanitize text content and replace newlines with <br> tags
            text = html.escape(note['content'])
            note_content_html = f'<div class="note-content"><p>{text}</p></div>'
            
        # Handle list notes
        elif note['content_type'] == 'list':
            unchecked_items = []
            checked_items = []
            
            for item in note['content']:
                # Sanitize list item text
                item_text = html.escape(item['text'])
                if item['is_checked']:
                    checked_items.append(
                        f'<li class="task-item"><input type="checkbox" disabled checked><span class="completed-item-text">{item_text}</span></li>'
                    )
                else:
                    unchecked_items.append(
                        f'<li class="task-item"><input type="checkbox" disabled><span>{item_text}</span></li>'
                    )
            
            # Combine unchecked items
            note_content_html += '<ul class="task-list">' + "".join(unchecked_items) + '</ul>'
            
            # Add checked items inside a collapsible <details> element
            if checked_items:
                item_count = len(checked_items)
                plural_s = 's' if item_count > 1 else ''
                note_content_html += f"""
                <details class="completed-items">
                    <summary>{item_count} completed item{plural_s}</summary>
                    <ul class="task-list">{"".join(checked_items)}</ul>
                </details>
                """
        
        # Combine title and content into a single note card
        html_body_content += f"""
        <div class="note-card" style="background-color: {bg_color};">
            <h2 class="note-title">{title}</h2>
            {note_content_html}
        </div>
        """
    # --- Final HTML Assembly ---
    full_html = f"""
{html_head}
<body>
    <h1>Troggle coding and design to-do lists</h1>
    <p>(Exported from Philip Sargent's Google Keep notes on {datetime.now().strftime('%Y-%m-%d %H:%M')})
    <p>Contact Philip if you wish to share these lists on your Google Keep account.
    <div class="container">
        {html_body_content}
    </div>
</body>
</html>
"""
    
    # --- Writing to File ---
    try:
        with open(filename, 'w', encoding='utf-8') as f:
            f.write(full_html)
        print(f"\n🎉 Successfully wrote {len(notes_data)} notes to '{filename}'")
    except Exception as e:
        print(f"❗️ An error occurred while writing the file: {e}")

# --- Run the program ---
if __name__ == "__main__":
    all_notes_data = process_keep_files_to_dict(TAKEOUT_DIRECTORY)

    if all_notes_data:
        print("\n" + "="*50)
        print("🎉 Successfully processed all matching files.")
        print(f"Total notes extracted: {len(all_notes_data)}")
        # print("Data has been stored in the 'all_notes_data' variable.")
        
        print("="*50)
        write_html_output(all_notes_data)