#include "browser_open.h"
#include "device_fileopen.h"
#include "device_identity.h"
#include "http_config_mqtt.h"

static char s_webcam[2048];//存放启动火狐网站命令
static int s_open_cam_enter_count = 0;      // 记录 opencamsh 进入次数
static int s_open_cam_fail_streak = 0;      // 连续启动失败次数
static int s_refresh_cam_enter_count = 0;   // 记录 refresh_cam 进入次数
static int s_refresh_cam_fail_count = 0;    // 刷新失败累计次数

#define REFRESH_CAM_COOLDOWN_SEC 20

static pthread_mutex_t s_refresh_stat_mutex = PTHREAD_MUTEX_INITIALIZER;
static pthread_mutex_t s_refresh_run_mutex = PTHREAD_MUTEX_INITIALIZER;
static pthread_mutex_t s_refresh_cool_mutex = PTHREAD_MUTEX_INITIALIZER;
static time_t s_refresh_next_allowed = 0; /* time(NULL) 之前不允许再提交刷新 */

int  opencamsh() {
    char urls[512];
    int cmd_ret = 0;

    s_open_cam_enter_count++;
    my_zlog_info("opencamsh enter count:%d", s_open_cam_enter_count);

    snprintf(urls, sizeof(urls), "%s%s", g_mqtt_cam_config_t->videourl, mqtt_topic_pure_number());

    //setenv("DISPLAY", ":0", 1);//设置环境变量https://jywy.yd-ss.com?dev=controcar0004 --new-window sudo 
    snprintf(s_webcam, sizeof(s_webcam), "su - orangepi -c \"chromium-browser --use-fake-ui-for-media-stream %s\"", urls);
    cmd_ret = system(s_webcam);
    if (cmd_ret != 0) {
        s_open_cam_fail_streak++;
        if (s_open_cam_fail_streak >= 10 && (s_open_cam_fail_streak % 10) == 0) {
            my_zlog_error("chromium start fail, ret:%d, continuous fail:%d, enter count:%d",
                          cmd_ret, s_open_cam_fail_streak, s_open_cam_enter_count);
        } else {
            my_zlog_warn("chromium start fail, ret:%d, continuous fail:%d, enter count:%d",
                         cmd_ret, s_open_cam_fail_streak, s_open_cam_enter_count);
        }
    } else {
        if (s_open_cam_fail_streak > 0) {
            my_zlog_info("chromium start recovered, previous continuous fail:%d", s_open_cam_fail_streak);
        }
        s_open_cam_fail_streak = 0;
    }
    my_zlog_debug("%s",s_webcam);
    my_zlog_debug("open cam");
    return 0;
}

/* 实际刷新逻辑：在后台线程执行，避免阻塞 MQTT 心跳线程 */
static void refresh_cam_impl(void)
{
    int refreshed_windows = 0;
    int failed_windows = 0;
    int enter = 0;

    pthread_mutex_lock(&s_refresh_stat_mutex);
    s_refresh_cam_enter_count++;
    enter = s_refresh_cam_enter_count;
    pthread_mutex_unlock(&s_refresh_stat_mutex);

    my_zlog_info("refresh_cam(async worker): start enter=%d", enter);

    setenv("DISPLAY", ":0", 1); // 确保 xdotool 在图形会话中执行
    setenv("XAUTHORITY", "/home/orangepi/.Xauthority", 1);//加入授权

    const char *search_command = "xdotool search --class \"chromium-browser\"";//获取窗口id

    FILE *fp = popen(search_command, "r");

    if (!fp) {
        pthread_mutex_lock(&s_refresh_stat_mutex);
        s_refresh_cam_fail_count++;
        int fc = s_refresh_cam_fail_count;
        pthread_mutex_unlock(&s_refresh_stat_mutex);
        my_zlog_error("refresh_cam outcome=FAIL reason=popen total_fail=%d enter=%d",
                      fc, enter);
        return;
    }

    char window_id[32];

    while (fgets(window_id, sizeof(window_id), fp) != NULL) {
        window_id[strcspn(window_id, "\n")] = '\0';

        char activate_command[128];

        snprintf(activate_command, sizeof(activate_command), "xdotool windowactivate %s key Ctrl+r", window_id);

        if (system(activate_command) == 0) {
            refreshed_windows++;
        } else {
            failed_windows++;
            my_zlog_warn("refresh_cam window command fail, window id:%s", window_id);
        }
    }

    pclose(fp);

    if (refreshed_windows == 0) {
        pthread_mutex_lock(&s_refresh_stat_mutex);
        s_refresh_cam_fail_count++;
        int fc = s_refresh_cam_fail_count;
        pthread_mutex_unlock(&s_refresh_stat_mutex);
        my_zlog_warn("refresh_cam outcome=FAIL reason=no_chromium_window total_fail=%d enter=%d",
                     fc, enter);
        return;
    }

    if (failed_windows > 0) {
        pthread_mutex_lock(&s_refresh_stat_mutex);
        s_refresh_cam_fail_count++;
        int fc = s_refresh_cam_fail_count;
        pthread_mutex_unlock(&s_refresh_stat_mutex);
        my_zlog_warn("refresh_cam outcome=FAIL reason=partial success=%d fail=%d total_fail=%d enter=%d",
                     refreshed_windows, failed_windows, fc, enter);
        return;
    }

    my_zlog_info("refresh_cam outcome=OK windows=%d enter=%d", refreshed_windows, enter);
}

static void *refresh_cam_worker(void *arg)
{
    (void)arg;
    pthread_mutex_lock(&s_refresh_run_mutex);
    refresh_cam_impl();
    pthread_mutex_unlock(&s_refresh_run_mutex);
    return NULL;
}

void refresh_cam(void)
{//刷新页面：异步提交，不阻塞 MQTT 收发线程
    pthread_mutex_lock(&s_refresh_cool_mutex);
    {
        time_t now = time(NULL);
        if (now < s_refresh_next_allowed) {
            long left = (long)(s_refresh_next_allowed - now);
            pthread_mutex_unlock(&s_refresh_cool_mutex);
            my_zlog_notice("refresh_cam skipped: cooldown %lds remaining (max once per %ds)",
                           left, REFRESH_CAM_COOLDOWN_SEC);
            return;
        }
    }
    pthread_mutex_unlock(&s_refresh_cool_mutex);

    pthread_t tid;
    pthread_attr_t attr;

    pthread_attr_init(&attr);
    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);

    if (pthread_create(&tid, &attr, refresh_cam_worker, NULL) != 0) {
        pthread_attr_destroy(&attr);
        my_zlog_error("refresh_cam outcome=FAIL reason=pthread_create errno=%s (未执行刷新)",
                      strerror(errno));
        return;
    }

    pthread_mutex_lock(&s_refresh_cool_mutex);
    s_refresh_next_allowed = time(NULL) + REFRESH_CAM_COOLDOWN_SEC;
    pthread_mutex_unlock(&s_refresh_cool_mutex);

    pthread_attr_destroy(&attr);
    my_zlog_info("refresh_cam outcome=PENDING (async submitted, mqtt thread not blocked, cooldown=%ds)",
                 REFRESH_CAM_COOLDOWN_SEC);
}

// 检查Chromium进程是否已运行
bool is_browser_running() {
    FILE *fp = popen("pgrep chromium", "r");
    if (fp == NULL) return false;

    char buf[16];
    bool running = (fgets(buf, sizeof(buf), fp) != NULL);
    pclose(fp);
    return running;
}
