import ephem
import datetime
import requests

from suntime import Sun, SunTimeException
from datetime import datetime
from dateutil import tz
from timezonefinder import TimezoneFinder

def get_sun_and_moon_phase(lat, long, date_str):
    curr_date = datetime.strptime(date_str, "%Y%m%d")
    date_str = f"{date_str[:4]}/{date_str[4:6]}/{date_str[6:8]}"

    my_tz = get_timezone(lat, long)
    sun = Sun(lat, long)
    sunrise_time = sun.get_sunrise_time(curr_date, tz.gettz(my_tz)).strftime("%H:%M:%S")
    sunset_time = sun.get_sunset_time(curr_date, tz.gettz(my_tz)).strftime("%H:%M:%S")

    date = ephem.Date(date_str)
    moon = ephem.Moon()
    moon.compute(date)

    return (sunrise_time, sunset_time, moon.phase)

def get_timezone(latitude: float, longitude: float):
    obj = TimezoneFinder()
    timezone_str = obj.timezone_at(lng=longitude, lat=latitude)
    return timezone_str

def get_weather(latitude: float, longitude: float, date_str: str, hour: int) -> dict:
    """
    Fetches weather data for the specified location and time.
    
    Args:
        latitude (float): Latitude of the location in degrees.
        longitude (float): Longitude of the location in degrees.
        date_str (str): Date in YYYYMMDD format.
        hour (int): Hour (0-23) when you want to know the weather.
    
    Returns:
        dict: Dictionary containing temperature, condition, and sunrise/sunset times.
    """
    # Convert date string components for API request
    date = f"{date_str[:4]}-{date_str[4:6]}-{date_str[6:8]}"

    stats_to_get = [
        "temperature_2m",
        "relative_humidity_2m",
        "dew_point_2m",
        "apparent_temperature",
        "pressure_msl",
        "surface_pressure",
        "precipitation",
        "rain",
        "snowfall",
        "cloud_cover",
        "cloud_cover_low",
        "cloud_cover_mid",
        "cloud_cover_high",
        "shortwave_radiation",
        "direct_radiation",
        "direct_normal_irradiance",
        "diffuse_radiation",
        "global_tilted_irradiance",
        "sunshine_duration",
        "wind_speed_10m",
        "wind_speed_100m",
        "wind_direction_10m",
        "wind_direction_100m",
        "wind_gusts_10m",
        "et0_fao_evapotranspiration",
        "weather_code",
        "snow_depth",
        "vapour_pressure_deficit",
        "soil_temperature_0_to_7cm",
        "soil_temperature_7_to_28cm",
        "soil_temperature_28_to_100cm",
        "soil_temperature_100_to_255cm",
        "soil_moisture_0_to_7cm",
        "soil_moisture_7_to_28cm",
        "soil_moisture_28_to_100cm",
        "soil_moisture_100_to_255cm",
    ]

    stats_to_get = ','.join(stats_to_get)
    timezone = get_timezone(latitude, longitude)

    try:
        api_url = f"https://archive-api.open-meteo.com/v1/archive?latitude={latitude}&longitude={longitude}&timezone={timezone}&start_date={date}&end_date={date}&hourly={stats_to_get}"
        response = requests.get(api_url)
        data = response.json()
        
        if response.status_code != 200:
            return {"error": "Failed to fetch weather", "details": data}

        return data
    
    except Exception as e:
        return {"error": str(e), "details": f"No weather data available for {latitude}, {longitude} on {date_str}"}
