import os
from dotenv import load_dotenv
import json
import base64
import smtplib
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
from email.mime.image import MIMEImage
from datetime import datetime
from flask import Flask, request, jsonify, render_template


load_dotenv()
app = Flask(__name__)

# --- CONFIGURATION ---
UPLOAD_FOLDER = 'static/uploads'
DATA_FILE = 'box_data.json'
os.makedirs(UPLOAD_FOLDER, exist_ok=True)

# EMAIL CONFIG (Read from .env)
SMTP_SERVER = os.getenv('SMTP_SERVER', 'mail.example.com')
SMTP_PORT = int(os.getenv('SMTP_PORT', 587))
SENDER_EMAIL = os.getenv('SENDER_EMAIL', 'firebot@exmaple.com')
SENDER_PASSWORD = os.getenv('SENDER_PASSWORD', 'password')
OWNER_EMAIL = os.getenv('OWNER_EMAIL', 'mail.ex@mail.com')

# --- STATE MANAGEMENT ---
def load_data():
    if not os.path.exists(DATA_FILE):
        # Default PIN is 1234 if file doesn't exist
        return {"pin": "1234", "logs": []}
    with open(DATA_FILE, 'r') as f:
        return json.load(f)

def save_data(data):
    with open(DATA_FILE, 'w') as f:
        json.dump(data, f)

# Global variables (RAM)
box_state = {
    "force_open": False,
    "force_close": False, # New: Remote Lock
    "stop_alarm": False,
    "trigger_check": False, # New: On-Demand Photo
    "is_locked": True
}

# --- EMAIL FUNCTION ---
def send_alert_email(image_filename, reason):
    try:
        msg = MIMEMultipart()
        msg['Subject'] = f"BOX ALERT: {reason}"
        msg['From'] = SENDER_EMAIL
        msg['To'] = OWNER_EMAIL
        text = MIMEText(f"Event: {reason}\nTime: {datetime.now()}")
        msg.attach(text)
        
        img_path = os.path.join(UPLOAD_FOLDER, image_filename)
        if os.path.exists(img_path):
            with open(img_path, 'rb') as f:
                img_data = f.read()
            image = MIMEImage(img_data, name=os.path.basename(image_filename))
            msg.attach(image)

        server = smtplib.SMTP(SMTP_SERVER, SMTP_PORT)
        server.starttls()
        server.login(SENDER_EMAIL, SENDER_PASSWORD)
        server.sendmail(SENDER_EMAIL, OWNER_EMAIL, msg.as_string())
        server.quit()
    except Exception as e:
        print(f"Email Error: {e}")

# --- ROUTES ---

@app.route('/')
def index():
    return render_template('index.html')

@app.route('/api/status', methods=['GET'])
def get_status_for_app():
    data = load_data()
    return jsonify({
        "box_state": box_state,
        "pin": data['pin'],
        "logs": data['logs'][-5:] 
    })

# --- ESP32 COMMUNICATION ---

@app.route('/api/esp/poll', methods=['GET'])
def esp_poll():
    print("Esp polling");
    """ESP32 Polls this for commands"""
    response = {
        "open_cmd": box_state["force_open"],
        "close_cmd": box_state["force_close"],
        "silence_cmd": box_state["stop_alarm"],
        "check_cmd": box_state["trigger_check"]
    }
    # Reset triggers
    if box_state["stop_alarm"]: box_state["stop_alarm"] = False
    if box_state["trigger_check"]: box_state["trigger_check"] = False
    
    return jsonify(response)

@app.route('/api/esp/update', methods=['POST'])
def esp_update():
    """ESP32 reports status"""
    data = request.json
    box_state["is_locked"] = data.get("locked", True)
    
    # Confirm commands executed
    if not box_state["is_locked"]: box_state["force_open"] = False
    if box_state["is_locked"]: box_state["force_close"] = False
        
    return "OK", 200

@app.route('/api/esp/upload', methods=['POST'])
def upload_image():
    try:
        data = request.json
        image_data = data['image']
        alert_type = data['type'] 

        filename = f"{datetime.now().strftime('%Y%m%d_%H%M%S')}.jpg"
        filepath = os.path.join(UPLOAD_FOLDER, filename)
        with open(filepath, "wb") as fh:
            fh.write(base64.b64decode(image_data))

        # Log it
        app_data = load_data()
        log_entry = {"time": datetime.now().strftime('%H:%M:%S'), "event": alert_type, "image": filename}
        app_data['logs'].append(log_entry)
        save_data(app_data)

        # Only email on critical alerts (Not on manual check)
        if "Check" not in alert_type:
            send_alert_email(filename, alert_type)

        return "Processed", 200
    except Exception as e:
        print(e)
        return "Error", 500

# --- APP CONTROLS ---

@app.route('/api/control/<action>', methods=['POST'])
def remote_control(action):
    if action == 'open': box_state["force_open"] = True
    elif action == 'close': box_state["force_close"] = True
    elif action == 'silence': box_state["stop_alarm"] = True
    elif action == 'check': box_state["trigger_check"] = True
    return jsonify({"status": f"{action} sent"})

@app.route('/api/control/setpin', methods=['POST'])
def set_pin():
    new_pin = request.json.get('pin')
    # Validate it's 4 digits
    if new_pin and len(new_pin) == 4 and new_pin.isdigit():
        data = load_data()
        data['pin'] = new_pin
        save_data(data) # Save to JSON file
        return jsonify({"status": "Updated"})
    return jsonify({"error": "Invalid PIN"}), 400

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=5000, debug=True)