#ifndef HASH_TABLE_H
#define HASH_TABLE_H

#include <stdlib.h>
#include <string.h>

#define TABLE_SIZE 16

typedef struct Entry {
    char* key;
    int value;
    struct Entry* next;
} Entry;

typedef struct HashTable {
    Entry* buckets[TABLE_SIZE];
    int size;
} HashTable;

static unsigned int hash(const char* key) {
    unsigned int hash = 0;
    for (int i = 0; key[i] != '\0'; i++) {
        hash = hash * 31 + (unsigned char)key[i];
    }
    return hash % TABLE_SIZE;
}

HashTable* ht_create() {
    HashTable* ht = (HashTable*)calloc(1, sizeof(HashTable));
    return ht;
}

void ht_insert(HashTable* ht, const char* key, int value) {
    if (ht == NULL || key == NULL) return;
    
    unsigned int index = hash(key);
    Entry* entry = ht->buckets[index];
    
    // Check if key exists
    while (entry != NULL) {
        if (strcmp(entry->key, key) == 0) {
            entry->value = value;
            return;
        }
        entry = entry->next;
    }
    
    // Create new entry
    Entry* new_entry = (Entry*)malloc(sizeof(Entry));
    new_entry->key = strdup(key);
    new_entry->value = value;
    new_entry->next = ht->buckets[index];
    ht->buckets[index] = new_entry;
    ht->size++;
}

int ht_get(HashTable* ht, const char* key, int* value) {
    if (ht == NULL || key == NULL) return 0;
    
    unsigned int index = hash(key);
    Entry* entry = ht->buckets[index];
    
    while (entry != NULL) {
        if (strcmp(entry->key, key) == 0) {
            if (value) *value = entry->value;
            return 1;
        }
        entry = entry->next;
    }
    
    return 0;
}

int ht_delete(HashTable* ht, const char* key) {
    if (ht == NULL || key == NULL) return 0;
    
    unsigned int index = hash(key);
    Entry* entry = ht->buckets[index];
    Entry* prev = NULL;
    
    while (entry != NULL) {
        if (strcmp(entry->key, key) == 0) {
            if (prev) {
                prev->next = entry->next;
            } else {
                ht->buckets[index] = entry->next;
            }
            free(entry->key);
            free(entry);
            ht->size--;
            return 1;
        }
        prev = entry;
        entry = entry->next;
    }
    
    return 0;
}

void ht_free(HashTable* ht) {
    if (ht == NULL) return;
    
    for (int i = 0; i < TABLE_SIZE; i++) {
        Entry* entry = ht->buckets[i];
        while (entry != NULL) {
            Entry* temp = entry;
            entry = entry->next;
            free(temp->key);
            free(temp);
        }
    }
    free(ht);
}

#endif