app.py
```
# app.py

import os
import shutil
import json
import logging
import time
import uuid
from logging.handlers import RotatingFileHandler
from datetime import datetime
from flask import Flask, render_template, request, redirect, url_for, send_file
from docx import Document
import pythoncom
from docx2pdf import convert
import re

app = Flask(__name__)

# Configure logging
def setup_logging():
    if not os.path.exists('logs'):
        os.makedirs('logs')
    handler = RotatingFileHandler('logs/app.log', maxBytes=5*1024*1024, backupCount=5)
    logging.basicConfig(handlers=[handler], level=logging.INFO, format='%(asctime)s %(levelname)s: %(message)s')

setup_logging()

# Utility functions
def log_action(action):
    logging.info(action)
    print(action)

def ensure_directory(path):
    if not os.path.exists(path):
        os.makedirs(path)
        log_action(f"Created directory '{path}'.")

def is_file_in_use(filepath):
    """Check if a file is in use by trying to open it in exclusive mode."""
    if os.path.exists(filepath):
        try:
            os.rename(filepath, filepath)  # Try renaming the file to itself
            return False
        except OSError:
            return True
    return False

def replace_keywords_in_docx(template_path, output_dir, replacements):
    try:
        ensure_directory(output_dir)
        zone_docx_path = os.path.join(output_dir, 'report_zone.docx')
        shutil.copy(template_path, zone_docx_path)
        log_action(f"Copied '{template_path}' to '{zone_docx_path}'.")

        doc = Document(zone_docx_path)

        # Compile regex patterns for keywords
        keyword_patterns = {re.escape(keyword): replacement for keyword, replacement in replacements.items()}
        combined_pattern = re.compile("|".join(keyword_patterns.keys()))

        def replace_in_runs(runs):
            for run in runs:
                if combined_pattern.search(run.text):
                    # Replace all occurrences of the keywords in the run's text
                    new_text = combined_pattern.sub(lambda match: replacements[match.group(0)], run.text)
                    log_action(f"Replaced text in run: '{run.text}' -> '{new_text}'")
                    run.text = new_text

        # Function to replace text in all runs in a paragraph
        def replace_in_paragraph(paragraph):
            replace_in_runs(paragraph.runs)

        # Replace keywords in document body
        for paragraph in doc.paragraphs:
            replace_in_paragraph(paragraph)

        # Replace keywords in tables
        for table in doc.tables:
            for row in table.rows:
                for cell in row.cells:
                    for paragraph in cell.paragraphs:
                        replace_in_paragraph(paragraph)

        # Replace keywords in headers and footers
        for section in doc.sections:
            header = section.header
            footer = section.footer
            # Replace in header
            for paragraph in header.paragraphs:
                replace_in_paragraph(paragraph)
            # Replace in footer
            for paragraph in footer.paragraphs:
                replace_in_paragraph(paragraph)

        # Prepare to save the modified document
        base_docx_name = f"{replacements.get('Keyword1', 'report')}.docx"
        new_docx_path = os.path.join(output_dir, base_docx_name)

        # Ensure the document is not open in another application
        if is_file_in_use(new_docx_path):
            log_action(f"File '{new_docx_path}' is in use. Saving with a unique name.")
            unique_id = uuid.uuid4().hex
            base_docx_name = f"{replacements.get('Keyword1', 'report')}_{unique_id}.docx"
            new_docx_path = os.path.join(output_dir, base_docx_name)

        # Save the modified document
        doc.save(new_docx_path)
        doc = None  # Release the Document object
        log_action(f"Modified document saved as '{base_docx_name}'.")

        return new_docx_path  # Return the path to the new document

    except Exception as e:
        logging.error(f"Error in replace_keywords_in_docx: {e}")
        raise

def convert_docx_to_pdf(docx_path, pdf_path):
    try:
        log_action(f"Converting '{docx_path}' to PDF.")
        # Ensure output directory exists
        ensure_directory(os.path.dirname(pdf_path))
        # Initialize COM components
        pythoncom.CoInitialize()
        # Convert DOCX to PDF using docx2pdf
        convert(docx_path, pdf_path)
        log_action(f"Converted '{docx_path}' to PDF '{pdf_path}'.")
        # Uninitialize COM components
        pythoncom.CoUninitialize()
    except Exception as e:
        logging.error(f"Error converting DOCX to PDF: {e}")
        raise

def save_uploaded_file(file, save_path):
    ensure_directory(os.path.dirname(save_path))
    file.save(save_path)
    log_action(f"Uploaded file saved to '{save_path}'.")

# Additional utility function
def get_reports_tree(base_path):
    reports_tree = {}
    for root, dirs, files in os.walk(base_path):
        parts = root.replace(base_path, '').strip(os.sep).split(os.sep)
        subtree = reports_tree
        for part in parts:
            if part:
                subtree = subtree.setdefault(part, {})
        for file in files:
            subtree.setdefault('files', []).append(file)
    return reports_tree

# Routes
@app.route('/')
def index():
    log_action("Accessed the main page.")
    return render_template('index.html', back_url=None)

@app.route('/create_report', methods=['GET', 'POST'])
def create_report():
    back_url = url_for('index')
    with open('config.json', 'r') as f:
        config = json.load(f)
    if request.method == 'POST':
        data = request.form.to_dict()
        # Prepare replacements
        replacements = {field['keyword']: data.get(field['field_name'], '') for section in config.values() for field in section}
        log_action(f"Replacements Dictionary: {replacements}")
        # Define paths
        template_path = os.path.join('reports', 'Section1', 'report.docx')
        output_dir = os.path.join('reports', 'Section1')
        # Replace keywords and get the path to the new docx file
        new_docx_path = replace_keywords_in_docx(template_path, output_dir, replacements)
        # Set pdf path based on the new docx path
        pdf_name = os.path.splitext(os.path.basename(new_docx_path))[0] + '.pdf'
        pdf_path = os.path.join(output_dir, pdf_name)
        convert_docx_to_pdf(new_docx_path, pdf_path)
        return redirect(url_for('index'))
    else:
        log_action("Accessed the create report page.")
        return render_template('create_report.html', config=config, back_url=back_url)

@app.route('/upload_report', methods=['GET', 'POST'])
def upload_report():
    back_url = url_for('index')
    if request.method == 'POST':
        file = request.files['report_file']
        report_date = request.form['report_date']
        date_obj = datetime.strptime(report_date, '%Y-%m-%d')
        save_dir = os.path.join('reports', 'Section1', 'Reports', str(date_obj.year), str(date_obj.month), str(date_obj.day))
        save_path = os.path.join(save_dir, file.filename)
        save_uploaded_file(file, save_path)
        return redirect(url_for('index'))
    else:
        log_action("Accessed the upload report page.")
        return render_template('upload_report.html', back_url=back_url)

@app.route('/view_reports')
def view_reports():
    back_url = url_for('index')
    base_path = os.path.join('reports', 'Section1', 'Reports')
    reports_tree = get_reports_tree(base_path)
    log_action("Accessed the view reports page.")
    return render_template('view_reports.html', reports_tree=reports_tree, back_url=back_url)

@app.route('/view_report/<path:filename>')
def view_report(filename):
    file_path = os.path.join('reports', 'Section1', 'Reports', filename)
    if os.path.exists(file_path):
        log_action(f"Serving report '{file_path}'.")
        return send_file(file_path)
    else:
        log_action(f"Report '{file_path}' not found.")
        return "Report not found.", 404

# Start the Flask application
if __name__ == '__main__':
    app.run(debug=True)

```

config.json
```
{
    "Section1": [
        {
            "field_name": "name",
            "field_text": "Name",
            "keyword": "keyword1"
        },
        {
            "field_name": "date",
            "field_text": "Date",
            "keyword": "keyword2"
        },
        {
            "field_name": "location",
            "field_text": "Location",
            "keyword": "keyword3"
        },
        {
            "field_name": "description",
            "field_text": "Description",
            "keyword": "keyword4"
        }
    ]
}
```
base.html
```
<!DOCTYPE html>
<html>
<head>
    <title>Project Moana</title>
</head>
<body>
    <nav>
        <a href="{{ url_for('index') }}">Home</a>
    </nav>
    {% block content %}{% endblock %}
    {% if back_url %}
        <button onclick="window.location.href='{{ back_url }}'">Back</button>
    {% endif %}
</body>
</html>
```

index.html
```
{% extends "base.html" %}
{% block content %}
<h1>Main Page</h1>
<ul>
    <li><a href="{{ url_for('create_report') }}">Create a Report</a></li>
    <li><a href="{{ url_for('upload_report') }}">Upload a Report</a></li>
    <li><a href="{{ url_for('view_reports') }}">Reports</a></li>
</ul>
{% endblock %}
```

create_report.html
```
{% extends "base.html" %}
{% block content %}
<h1>Create a Report</h1>
<form method="post">
    {% for section, fields in config.items() %}
        <h2>{{ section }}</h2>
        {% for field in fields %}
            <label>{{ field.field_text }}:</label>
            <input type="text" name="{{ field.field_name }}"><br>
        {% endfor %}
    {% endfor %}
    <input type="submit" value="Submit">
</form>
{% endblock %}
```

upload_report.html
```
{% extends "base.html" %}
{% block content %}
<h1>Upload a Report</h1>
<form method="post" enctype="multipart/form-data">
    <label>Select Report File (PDF):</label>
    <input type="file" name="report_file" accept="application/pdf" required><br>
    <label>Select Report Date:</label>
    <input type="date" name="report_date" required><br>
    <input type="submit" value="Upload">
</form>
{% endblock %}
```

view_reports.html
```
{% extends "base.html" %}
{% block content %}
<h1>Reports</h1>
<ul>
    {% for year, months in reports_tree.items() %}
        <li>
            <details>
                <summary>{{ year }}</summary>
                <ul>
                    {% for month, days in months.items() %}
                        <li>
                            <details>
                                <summary>{{ month }}</summary>
                                <ul>
                                    {% for day, content in days.items() %}
                                        {% if day != 'files' %}
                                            <li>
                                                <details>
                                                    <summary>{{ day }}</summary>
                                                    <ul>
                                                        {% for file in content.get('files', []) %}
                                                            <li><a href="{{ url_for('view_report', filename=year + '/' + month + '/' + day + '/' + file) }}">{{ file }}</a></li>
                                                        {% endfor %}
                                                    </ul>
                                                </details>
                                            </li>
                                        {% endif %}
                                    {% endfor %}
                                    {% if days.get('files') %}
                                        {% for file in days.get('files') %}
                                            <li><a href="{{ url_for('view_report', filename=year + '/' + month + '/' + file) }}">{{ file }}</a></li>
                                        {% endfor %}
                                    {% endif %}
                                </ul>
                            </details>
                        </li>
                    {% endfor %}
                </ul>
            </details>
        </li>
    {% endfor %}
</ul>
{% endblock %}
```

something is wrong with the app.py code 
it should : 
i need to create a python flask project, that would be part of another big project 
i need it organized and well tighten 

system: 
i have installed python 
created  a new folder in E 
Named E:\_projects\Project_moana
inside of it i need to create the uitable environemetn for the app 

it should have 
1 page of html where it has :
button1 [create a report] 
button2 [upload a report] 
button3 [reports] 

button1 should direct us to a page of html that has a template form like text box and text labels 
the template should be linked to a json config file where in json it would be like this : 
Section1 
field name , field text for user  ,Keyword1
field name , field text for user  ,Keyword2
field name , field text for user  ,Keyword3
field name , field text for user  ,Keyword4
where in the html page each field name is a text box , and each field text for user is a text appears next to the field on that html 
for example : 
[html of the template ]
Name |_____|
Date |_____| 
button to submit data and generate report 

then when we fill the report [it is ok to have some empty textboxes ] we click submit 
when that button is clicked the report is generated 
the mechanism of generating the report : 
there is a docx file named "report.docx" it has inside of it some typings and text like : 
report.docx
```some line 1 Keyword1 in this context where some line 2 Keyword3 is in context 
```
now when the user clicks submit report 
the file report.docx will be copied and paste into the same directory 
under the name [report_zone.docx] where any changes made will be for this file 
the keywords should be changed to the data from user 
such as Keyword1 , and Keyword3 [all keywords should be changed to the textbox data corresponded to it] 
once the new copied file is complete in all keywords 
a log will occur 
where it tells you [keywords : 
... has been replaced with ... 
... has been replaced with ... 
... has been replaced with ... 
]
then the file will be saved for these new changes 
the file will be saved under a new name, that name is "keyword1" [the textbox data that should replace keyword1 ]
then the file will be converted into pdf file under the same name as is [the textbox data that should replace keyword1]

that is for button1 then we need to have the following for button2 
button2 is for uploading a reaport where it is a pdf report 
when this button is clicked a new html page should appear 
this one would have a button to upload a rport 
a date calender to determine the date of the report [for example i could create a report at 01-01-2024 and want to tupload it at 01-10-2024 ] 
so the date i should choose for each report 
once the date is selected the report should be uploaded and saved into a folder named [Section1/Reports/[year]/[month]/[day]] 
that is for button 2 

button3 
this one will show us a new html page where it would have the following : 
sections by the year 
like 2024
2023
2022 
and so on 
the year is collapsed , when clicked it reveals the months within it 
each month is the same collapsed, until clicked to reveal the days inside of it 
as well as the days too same priniciple 
the year, month, and day should be only the ones that have been already created [no need to show all the years, and all the months of everything , nope, you should only make the dates that only have files in it visible ]
like if i have : 
> file date is 2024\11\1 
> file date is 2023\5\26 
then only the year 2024 and 2023 would appear  
within the year 2024 only the month 11 would appear and with in it only the day 1 would appear where it has a report file 
within the year 2023 only the month 5 would appear and with in it only the day 26 would appear where it has a report file 

when revealed the files it is clickable 
you can open the report file in the browser itself 




everything happens must be printed out [in cmd] and logged too [log file -where new things are on top , and the old ones are after it ,the old ones dont get deleted , and log files are kept till 5 files are created with 5 mega bytes size-]
any thing that needs to happen no matter how small it is must be converted into a function 
where that function is called whenver needed 
no repeated codes [if you want to log what happens, create a function to log the functions, and just call it before that new function being called] 
as well as error handling , it also should  be treated like log function mechanism 
there mut be a bottom button for back [going back to the previouos page] 


so we need to fix the app.py code to make sure the repor.docx file stays the same , it must not change at all. 
the keywords should be correctly replaced, casue it was , but now it does not .