"""
Data module for nutrition pad application.
Handles daily logs, configuration loading, and nutrition statistics.
"""
import json
import os
import toml
from datetime import datetime, date

CONFIG_FILE = 'foods.toml'
LOGS_DIR = 'daily_logs'

# --- DEFAULT CONFIG (unit vs amount foods) ---
DEFAULT_CONFIG = """[pads.proteins]
name = "Proteins"

[pads.proteins.foods.unknown_amount]
name = "Unknown (amount)"
type = "amount"
calories_per_gram = 0.0
protein_per_gram = 0.0

[pads.proteins.foods.unknown_unit]
name = "Unknown (unit)"
type = "unit"
calories = 0
protein = 0

[pads.proteins.foods.chicken_breast]
name = "Chicken Breast"
type = "amount"
calories_per_gram = 1.46
protein_per_gram = 0.27

[pads.proteins.foods.ground_beef]
name = "Ground Beef"
type = "amount"
calories_per_gram = 2.50
protein_per_gram = 0.20

[pads.proteins.foods.salmon]
name = "Salmon"
type = "amount"
calories_per_gram = 1.77
protein_per_gram = 0.25

[pads.proteins.foods.eggs]
name = "Eggs (2 large)"
type = "unit"
calories = 140
protein = 12

[pads.vegetables]
name = "Vegetables"

[pads.vegetables.foods.broccoli]
name = "Broccoli"
type = "amount"
calories_per_gram = 0.34
protein_per_gram = 0.03

[pads.vegetables.foods.spinach]
name = "Spinach"
type = "amount"
calories_per_gram = 0.23
protein_per_gram = 0.03

[pads.carbs]
name = "Carbs"

[pads.carbs.foods.rice]
name = "Rice (cooked)"
type = "amount"
calories_per_gram = 1.30
protein_per_gram = 0.027

[pads.carbs.foods.oatmeal]
name = "Oatmeal (cooked)"
type = "amount"
calories_per_gram = 0.625
protein_per_gram = 0.021
"""

def ensure_logs_directory():
    """Create logs directory if it doesn't exist"""
    if not os.path.exists(LOGS_DIR):
        os.makedirs(LOGS_DIR)

def load_config():
    """Load TOML config file, create default if not exists"""
    if not os.path.exists(CONFIG_FILE):
        with open(CONFIG_FILE, 'w') as f:
            f.write(DEFAULT_CONFIG)
    
    with open(CONFIG_FILE, 'r') as f:
        return toml.load(f)

def get_today_log_file():
    """Get path to today's log file"""
    today = date.today().strftime('%Y-%m-%d')
    return os.path.join(LOGS_DIR, f'{today}.json')

def load_today_log():
    """Load today's food log"""
    log_file = get_today_log_file()
    
    if not os.path.exists(log_file):
        return []
    
    try:
        with open(log_file, 'r') as f:
            return json.load(f)
    except (json.JSONDecodeError, IOError):
        return []

def save_food_entry(pad_key, food_key, food_data, amount=None):
    """Save a food entry to today's log with specified amount or unit"""
    log_file = get_today_log_file()
    
    # Load existing entries
    entries = load_today_log()
    
    # Get current timestamp
    now = datetime.now()
    timestamp = now.isoformat()
    time_str = now.strftime('%H:%M')
    
    # Get scale factor (default 1.0)
    scale = food_data.get('scale', 1.0)
    
    # Calculate nutrition based on food type
    if food_data.get('type') == 'unit':
        # Unit food - fixed serving
        calories = food_data.get('calories', 0) * scale
        protein = food_data.get('protein', 0) * scale
        fiber = food_data.get('fiber', 0) * scale
        amount_display = "1 unit"
        entry_amount = 1
    else:
        # Amount food - calculate from grams
        if amount is None:
            amount = 100  # default to 100g
        calories = food_data.get('calories_per_gram', 0) * amount * scale
        protein = food_data.get('protein_per_gram', 0) * amount * scale
        fiber = food_data.get('fiber_per_gram', 0) * amount * scale
        amount_display = f"{amount}g"
        entry_amount = amount
    
    # Create entry
    entry = {
        'time': time_str,
        'pad': pad_key,
        'food': food_key,
        'name': food_data.get('name', food_key),
        'amount': entry_amount,
        'amount_display': amount_display,
        'calories': round(calories, 1),
        'protein': round(protein, 1),
        'fiber': round(fiber, 1),
        'timestamp': timestamp
    }
    
    entries.append(entry)
    
    # Save back to file
    with open(log_file, 'w') as f:
        json.dump(entries, f, indent=2)
    
    return entry

def calculate_daily_total():
    """Calculate total protein for today"""
    entries = load_today_log()
    return sum(entry.get('protein', 0) for entry in entries)

def calculate_daily_item_count():
    """Calculate total items logged for today"""
    return len(load_today_log())

def calculate_nutrition_stats():
    """Calculate comprehensive nutrition stats for today"""
    log = load_today_log()
    
    if not log:
        return {
            'total_calories': 0,
            'total_protein': 0,
            'total_fiber': 0,
            'avg_ratio': '--',
            'cal_per_hour': '--',
            'protein_per_hour': '--',
            'kcal_per_fiber': '--'
        }
    
    total_calories = sum(entry.get('calories', 0) for entry in log)
    total_protein = sum(entry.get('protein', 0) for entry in log)
    total_fiber = sum(entry.get('fiber', 0) for entry in log)
    
    # Calculate kcal per gram of protein (lower is better for protein efficiency)
    avg_ratio = total_calories / total_protein if total_protein > 0 else 0
    
    # Calculate kcal per gram of fiber
    kcal_per_fiber = total_calories / total_fiber if total_fiber > 0 else 0
    
    # Calculate hours since 5am
    now = datetime.now()
    five_am = now.replace(hour=5, minute=0, second=0, microsecond=0)
    if now < five_am:
        # Before 5am, count from previous day's 5am
        five_am = five_am.replace(day=five_am.day - 1)
    
    hours_since_5am = (now - five_am).total_seconds() / 3600
    hours_since_5am = max(hours_since_5am, 0.1)  # Avoid division by zero
    
    cal_per_hour = total_calories / hours_since_5am
    protein_per_hour = total_protein / hours_since_5am
    
    return {
        'total_calories': round(total_calories),
        'total_protein': round(total_protein, 1),
        'total_fiber': round(total_fiber, 1),
        'avg_ratio': f"{avg_ratio:.1f}",
        'cal_per_hour': f"{cal_per_hour:.0f}",
        'protein_per_hour': f"{protein_per_hour:.1f}",
        'kcal_per_fiber': f"{kcal_per_fiber:.0f}" if total_fiber > 0 else '--'
    }

def calculate_time_since_last_ate():
    """Calculate time since last food entry (excludes drinks/items under 20 kcal)"""
    entries = load_today_log()
    
    if not entries:
        return None
    
    # Filter to only "real food" (20+ kcal)
    food_entries = [e for e in entries if e.get('calories', 0) >= 20]
    
    if not food_entries:
        return None
    
    # Get the last food entry's timestamp
    last_entry = food_entries[-1]
    timestamp_str = last_entry.get('timestamp')
    
    if not timestamp_str:
        return None
    
    try:
        last_time = datetime.fromisoformat(timestamp_str)
        now = datetime.now()
        delta = now - last_time
        
        total_minutes = int(delta.total_seconds() / 60)
        
        return {
            'minutes': total_minutes,
            'timestamp': timestamp_str
        }
    except (ValueError, TypeError):
        return None

def validate_food_request(pad_key, food_key):
    """Validate that a pad and food key exist in the config"""
    config = load_config()
    
    if pad_key not in config.get('pads', {}):
        return False, 'Invalid pad'
        
    if food_key not in config['pads'][pad_key].get('foods', {}):
        return False, 'Invalid food'
    
    return True, config['pads'][pad_key]['foods'][food_key]

def get_food_data(pad_key, food_key):
    """Get food data for a specific pad and food key"""
    config = load_config()
    return config['pads'][pad_key]['foods'][food_key]

def get_all_pads():
    """Get all pads from the configuration"""
    config = load_config()
    return config.get('pads', {})