import obspython as obs
import time
import datetime
import os
import urllib.request
import json

# Globals
log_file_path       = ""
hotkey_id           = obs.OBS_INVALID_HOTKEY_ID
stream_start_time   = None
record_start_time   = None
user_stream_title   = ""
session_active = False
first_snap_in_session = False

# Credentials
twitch_user_login   = ""
twitch_client_id    = ""
twitch_oauth_token  = ""
youtube_api_key     = ""
youtube_channel_id  = ""
title_preference    = ""

def script_description():
    return (
        "Do not forget to set the 'Timestamp snap' hotkey.<br><br>"
        "If you are streaming to both Twitch and YouTube simultaneously, select the corresponding checkbox. "
        '<a href="https://github.com/OlexandrNikolaiev/OBS-Timestamper">Instructions</a>'
    )

def script_properties():
    props = obs.obs_properties_create()

    obs.obs_properties_add_path(props, "log_file", "Timestamp list location", obs.OBS_PATH_FILE_SAVE, "*.txt", None)
    obs.obs_properties_add_text(props, "stream_name", "Forced broadcast title \n(will be displayed in the list)", obs.OBS_TEXT_DEFAULT)

    obs.obs_properties_add_bool(props, "use_twitch", "Twitch Title Priority")

    obs.obs_properties_add_text(props, "twitch_user_login", "Twitch Login", obs.OBS_TEXT_DEFAULT)
    obs.obs_properties_add_text(props, "twitch_client_id", "Twitch Client ID", obs.OBS_TEXT_PASSWORD)
    obs.obs_properties_add_text(props, "twitch_oauth_token", "OAuth token", obs.OBS_TEXT_PASSWORD)

    obs.obs_properties_add_bool(props, "use_youtube", "YouTube Title Priority")
    obs.obs_properties_add_text(props, "youtube_api_key", "YouTube API Key", obs.OBS_TEXT_PASSWORD)
    obs.obs_properties_add_text(props, "youtube_channel_id", "YouTube Channel ID", obs.OBS_TEXT_PASSWORD)

    obs.obs_property_set_modified_callback(obs.obs_properties_get(props, "use_twitch"), on_twitch_radio_changed)
    obs.obs_property_set_modified_callback(obs.obs_properties_get(props, "use_youtube"), on_youtube_radio_changed)

    obs.obs_properties_add_button(props, "reset_timer", "                    Reset the timer manually                   ", reset_timer_callback)

    return props

def script_update(settings):
    global log_file_path, user_stream_title
    global twitch_user_login, twitch_client_id, twitch_oauth_token, youtube_api_key, youtube_channel_id

    log_file_path       = obs.obs_data_get_string(settings, "log_file")
    user_stream_title   = obs.obs_data_get_string(settings, "stream_name")
    twitch_user_login   = obs.obs_data_get_string(settings, "twitch_user_login")
    twitch_client_id    = obs.obs_data_get_string(settings, "twitch_client_id")
    twitch_oauth_token  = obs.obs_data_get_string(settings, "twitch_oauth_token")
    youtube_api_key     = obs.obs_data_get_string(settings, "youtube_api_key")
    youtube_channel_id  = obs.obs_data_get_string(settings, "youtube_channel_id")

def on_twitch_radio_changed(props, prop, settings):
    global title_preference
    if obs.obs_data_get_bool(settings, "use_twitch"):
        obs.obs_data_set_bool(settings, "use_youtube", False)
        title_preference = "twitch"
    return True

def on_youtube_radio_changed(props, prop, settings):
    global title_preference
    if obs.obs_data_get_bool(settings, "use_youtube"):
        obs.obs_data_set_bool(settings, "use_twitch", False)
        title_preference = "youtube"
    return True

def script_load(settings):
    global hotkey_id, stream_start_time, record_start_time
    hotkey_id = obs.obs_hotkey_register_frontend(
        "stream_timestamp_hotkey",
        "Timestamp snap",
        on_hotkey
    )
    saved = obs.obs_data_get_array(settings, "hotkey_array")
    obs.obs_hotkey_load(hotkey_id, saved)
    obs.obs_data_array_release(saved)

    obs.obs_frontend_add_event_callback(frontend_event_callback)
    stream_start_time = None
    record_start_time = None

def script_defaults(settings):
    default = os.path.join(os.path.expanduser("~"), "stream_timestamps.txt")
    obs.obs_data_set_default_string(settings, "log_file", default)
    obs.obs_data_set_default_bool(settings, "use_youtube", True)

def script_save(settings):
    arr = obs.obs_hotkey_save(hotkey_id)
    obs.obs_data_set_array(settings, "hotkey_array", arr)
    obs.obs_data_array_release(arr)

def frontend_event_callback(event):
    global stream_start_time, record_start_time, session_active, first_snap_in_session
    if event == obs.OBS_FRONTEND_EVENT_STREAMING_STARTED:
        stream_start_time = time.time()
        if not session_active:
            session_active = True
            first_snap_in_session = True
    elif event == obs.OBS_FRONTEND_EVENT_RECORDING_STARTED:
        record_start_time = time.time()
        if not session_active:
            session_active = True
            first_snap_in_session = True
    elif event in [obs.OBS_FRONTEND_EVENT_STREAMING_STOPPED,
                   obs.OBS_FRONTEND_EVENT_RECORDING_STOPPED]:
        if not obs.obs_frontend_streaming_active() and not obs.obs_frontend_recording_active():
            stream_start_time = None
            record_start_time = None
            session_active = False
            first_snap_in_session = False

def on_hotkey(pressed):
    is_active = obs.obs_frontend_streaming_active() or obs.obs_frontend_recording_active()
    if pressed and is_active:
        record_timestamp()
    elif pressed:
        pass

def reset_timer_callback(props, prop):
    global stream_start_time, record_start_time, log_file_path
    now = time.time()
    if obs.obs_frontend_streaming_active():
        stream_start_time = now
    if obs.obs_frontend_recording_active():
        record_start_time = now
    try:
        with open(log_file_path, "a", encoding="utf-8") as f:
            f.write("Timer was manually reset\n")
    except:
        pass
    return True

def fetch_recording_title():
    return "[Recording]"

def fetch_youtube_title():
    if not youtube_api_key or not youtube_channel_id:
        return ""
    try:
        url = (
            "https://www.googleapis.com/youtube/v3/search"
            f"?part=snippet&channelId={youtube_channel_id}"
            "&eventType=live&type=video"
            f"&key={youtube_api_key}"
        )
        resp = urllib.request.urlopen(url)
        data = json.load(resp)
        items = data.get("items", [])
        if items:
            return "[Youtube] " + items[0]["snippet"]["title"]
    except Exception as e:
        obs.script_log(obs.LOG_WARNING, f"YouTube API error: {e}")
    return ""

def fetch_twitch_title():
    if not twitch_client_id or not twitch_oauth_token or not twitch_user_login:
        return ""
    try:
        url = f"https://api.twitch.tv/helix/streams?user_login={twitch_user_login}"
        req = urllib.request.Request(url)
        req.add_header("Client-ID", twitch_client_id)
        req.add_header("Authorization", f"Bearer {twitch_oauth_token}")
        
        with urllib.request.urlopen(req) as resp:
            data = json.load(resp)
            streams = data.get("data", [])
            if streams:
                return f"[Twitch] {streams[0]['title']}"
    except Exception as e:
        obs.script_log(obs.LOG_WARNING, f"Twitch API error: {e}" + "\nA hint from the developer: probably OAuth token is expired")
    return ""

def record_timestamp():
    global first_snap_in_session, stream_start_time, record_start_time
    is_streaming = obs.obs_frontend_streaming_active()
    is_recording = obs.obs_frontend_recording_active()

    if is_streaming and stream_start_time:
        start_time = stream_start_time
    elif is_recording and record_start_time:
        start_time = record_start_time
    else:
        return

    elapsed = time.time() - start_time
    hh = int(elapsed // 3600)
    mm = int(elapsed // 60) % 60
    ss = int(elapsed % 60)
    ts = f"{hh:02d}:{mm:02d}:{ss:02d}"
    now = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")

    title = ""
    if is_streaming:
        if title_preference == "twitch":
            title = fetch_twitch_title() or fetch_youtube_title()
        else:
            title = fetch_youtube_title() or fetch_twitch_title()
    elif is_recording:
        title = fetch_recording_title()
    if not title:
        title = "[Unknown Title]"

    line = f"{title} | {now} | {ts}\n"

    try:
        with open(log_file_path, "a", encoding="utf-8") as f:
            if first_snap_in_session:
                f.write("\n") 
                first_snap_in_session = False
            f.write(line)
    except:
        pass

def script_unload():
    pass
