#include "browser_resolver.h"
#include "utils.h"
#include <stdlib.h>
#include <string.h>
#include <stdio.h>

BrowserList* browser_list_create(void) {
    BrowserList* list = malloc(sizeof(BrowserList));
    if (!list) return NULL;

    list->items = malloc(sizeof(BrowserInfo) * 4);
    if (!list->items) {
        free(list);
        return NULL;
    }

    list->count = 0;
    list->capacity = 4;
    return list;
}

void browser_list_destroy(BrowserList* list) {
    if (!list) return;
    free(list->items);
    free(list);
}

bool browser_list_add(BrowserList* list, const wchar_t* id, const wchar_t* path) {
    if (!list || !id || !path) return false;

    if (list->count >= list->capacity) {
        size_t new_cap = list->capacity * 2;
        BrowserInfo* new_items = realloc(list->items, sizeof(BrowserInfo) * new_cap);
        if (!new_items) return false;
        list->items = new_items;
        list->capacity = new_cap;
    }

    wcsncpy_s(list->items[list->count].browser_id, 64, id, _TRUNCATE);
    wcsncpy_s(list->items[list->count].exe_path, MAX_PATH_LEN, path, _TRUNCATE);
    list->count++;
    return true;
}

static bool query_registry_value(HKEY root, const wchar_t* subkey, wchar_t* out, size_t len) {
    wchar_t buffer[MAX_PATH];
    DWORD buffer_size = sizeof(buffer);

    LSTATUS status = RegGetValueW(root, subkey, NULL,
        RRF_RT_REG_SZ | RRF_RT_REG_EXPAND_SZ,
        NULL, buffer, &buffer_size);

    if (status == ERROR_SUCCESS) {
        wcsncpy_s(out, len, buffer, _TRUNCATE);
        return true;
    }

    if (status == ERROR_MORE_DATA) {
        wchar_t* long_buffer = malloc(buffer_size);
        if (!long_buffer) return false;

        status = RegGetValueW(root, subkey, NULL,
            RRF_RT_REG_SZ | RRF_RT_REG_EXPAND_SZ,
            NULL, long_buffer, &buffer_size);

        if (status == ERROR_SUCCESS) {
            wcsncpy_s(out, len, long_buffer, _TRUNCATE);
            free(long_buffer);
            return true;
        }
        free(long_buffer);
    }

    return false;
}

bool browser_resolve_path(const wchar_t* exe_name, wchar_t* out_path, size_t len) {
    if (!exe_name || !out_path) return false;

    wchar_t subkey[512];

    const struct {
        HKEY root;
        const wchar_t* base_path;
    } locations[] = {
        { HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\App Paths\\" },
        { HKEY_CURRENT_USER,  L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\App Paths\\" },
        { HKEY_LOCAL_MACHINE, L"SOFTWARE\\WOW6432Node\\Microsoft\\Windows\\CurrentVersion\\App Paths\\" }
    };

    for (size_t i = 0; i < sizeof(locations) / sizeof(locations[0]); i++) {
        swprintf_s(subkey, 512, L"%s%s", locations[i].base_path, exe_name);

        if (query_registry_value(locations[i].root, subkey, out_path, len)) {
            if (file_exists(out_path)) {
                return true;
            }
        }
    }

    return false;
}

BrowserList* browser_find_all_installed(void) {
    BrowserList* list = browser_list_create();
    if (!list) return NULL;

    const struct {
        const wchar_t* id;
        const wchar_t* exe;
    } targets[] = {
        { L"chrome", L"chrome.exe" },
        { L"brave",  L"brave.exe" }
    };

    for (size_t i = 0; i < sizeof(targets) / sizeof(targets[0]); i++) {
        wchar_t path[MAX_PATH_LEN];
        if (browser_resolve_path(targets[i].exe, path, MAX_PATH_LEN)) {
            browser_list_add(list, targets[i].id, path);
        }
    }

    return list;
}