#!/usr/bin/env python3
"""
Cariflex - Automatic Scheduling Service
Creates battery/EV schedules based on OpenADR price signals and flexibility events.
"""

import json, logging, os, sys
from datetime import datetime, timezone, timedelta

# Add FM path
sys.path.insert(0, '/app')

logging.basicConfig(level=logging.INFO)
logger = logging.getLogger("cariflex-scheduling")

# FM imports
from flexmeasures.data.models.planning.storage import StorageScheduler
from flexmeasures.data.services.scheduling import make_schedule
from flexmeasures.data.models.generic_asset import GenericAsset
from flexmeasures.data.models.sensor import Sensor
from flexmeasures.data import db

# Scheduling config
SCHEDULING_CONFIG = {
    "battery_sensors": list(range(51, 61)),  # Bat_01 to Bat_10
    "ev_sensors": list(range(61, 71)),        # EV_01 to EV_10
    "price_sensor": 84,                        # consumption_price (OpenADR)
    "load_control_sensor": 86,                 # load_control_signal (OpenADR)
    "demand_response_sensor": 87,              # demand_response_signal (OpenADR)
    "planning_horizon_hours": 24,
    "resolution_minutes": 15,
}


def get_sensor_data(sensor_id, start, end):
    """Get sensor data from FM database."""
    sensor = db.session.query(Sensor).filter(Sensor.id == sensor_id).first()
    if not sensor:
        return None
    
    beliefs = db.session.query(
        TimedBelief.event_start, TimedBelief.event_value
    ).filter(
        TimedBelief.sensor_id == sensor_id,
        TimedBelief.event_start >= start,
        TimedBelief.event_start <= end
    ).order_by(TimedBelief.event_start).all()
    
    return beliefs


def create_battery_schedule(sensor_id, start_time, duration_hours=24):
    """Create a schedule for a battery based on price signals."""
    from flexmeasures.data.models.sensor import Sensor
    from flexmeasures.data.models.generic_asset import GenericAsset
    
    sensor = db.session.query(Sensor).filter(Sensor.id == sensor_id).first()
    if not sensor:
        logger.warning(f"Sensor {sensor_id} not found")
        return None
    
    asset = db.session.query(GenericAsset).filter(GenericAsset.id == sensor.generic_asset_id).first()
    if not asset:
        logger.warning(f"Asset for sensor {sensor_id} not found")
        return None
    
    logger.info(f"Creating schedule for {asset.name} (sensor {sensor_id})")
    
    # Get price data
    end_time = start_time + timedelta(hours=duration_hours)
    price_sensor = db.session.query(Sensor).filter(Sensor.id == SCHEDULING_CONFIG["price_sensor"]).first()
    
    if not price_sensor:
        logger.warning("Price sensor not found")
        return None
    
    # Create schedule using FM's built-in scheduler
    try:
        schedule = make_schedule(
            sensor=sensor,
            start=start_time,
            end=end_time,
            resolution=timedelta(minutes=SCHEDULING_CONFIG["resolution_minutes"]),
            flex_model={
                "soc-min": "0.1 MWh",
                "soc-max": "1 MWh",
                "power-capacity": "0.05 MW",
                "charging-efficiency": "0.95",
                "discharging-efficiency": "0.95",
            }
        )
        logger.info(f"Schedule created for {asset.name}: {len(schedule) if schedule else 0} points")
        return schedule
    except Exception as e:
        logger.error(f"Scheduling error for {asset.name}: {e}")
        return None


def run_scheduling():
    """Run scheduling for all batteries and EVs."""
    logger.info("Starting automatic scheduling...")
    
    now = datetime.now(timezone.utc)
    start_time = now.replace(minute=0, second=0, microsecond=0)
    
    # Schedule batteries
    for sensor_id in SCHEDULING_CONFIG["battery_sensors"]:
        try:
            create_battery_schedule(sensor_id, start_time)
        except Exception as e:
            logger.error(f"Error scheduling battery {sensor_id}: {e}")
    
    # Schedule EVs
    for sensor_id in SCHEDULING_CONFIG["ev_sensors"]:
        try:
            create_battery_schedule(sensor_id, start_time)
        except Exception as e:
            logger.error(f"Error scheduling EV {sensor_id}: {e}")
    
    logger.info("Scheduling complete")


if __name__ == "__main__":
    # Run scheduling every 15 minutes
    import time
    while True:
        try:
            run_scheduling()
        except Exception as e:
            logger.error(f"Scheduling error: {e}")
        time.sleep(900)  # 15 minutes
