#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <dirent.h>
#include <sys/stat.h>

#define BUFFER_SIZE 1024

void send_response(int client_socket, const char *status, const char *content_type, const char *body) {
    char response[BUFFER_SIZE];
    sprintf(response, "HTTP/1.1 %s\r\nContent-Type: %s\r\nContent-Length: %zu\r\n\r\n%s", 
            status, content_type, strlen(body), body);
    send(client_socket, response, strlen(response), 0);
}

void serve_file(int client_socket, const char *file_path) {
    FILE *file = fopen(file_path, "r");
    if (file == NULL) {
        // Serve a custom 404 page if the file is not found
        const char *not_found_page = "<html><body><h1>404 Not Found</h1><p>The requested file was not found on the server.</p></body></html>";
        send_response(client_socket, "404 Not Found", "text/html", not_found_page);
        return;
    }

    fseek(file, 0, SEEK_END);
    long file_size = ftell(file);
    fseek(file, 0, SEEK_SET);
    
    char *file_content = malloc(file_size + 1);
    fread(file_content, 1, file_size, file);
    file_content[file_size] = '\0';
    fclose(file);

    send_response(client_socket, "200 OK", "text/html", file_content);
    free(file_content);
}

void handle_request(int client_socket, const char *folder) {
    char buffer[BUFFER_SIZE];
    recv(client_socket, buffer, sizeof(buffer) - 1, 0);
    
    char method[10], path[BUFFER_SIZE];
    sscanf(buffer, "%s %s", method, path);
    
    if (strcmp(method, "GET") == 0) {
        // Serve index.html for root path
        if (strcmp(path, "/") == 0) {
            char file_path[BUFFER_SIZE];
            snprintf(file_path, sizeof(file_path), "%s/index.html", folder);
            serve_file(client_socket, file_path);
        } else {
            char file_path[BUFFER_SIZE];
            snprintf(file_path, sizeof(file_path), "%s%s", folder, path);
            serve_file(client_socket, file_path);
        }
    } else {
        send_response(client_socket, "405 Method Not Allowed", "text/plain", "Method not allowed");
    }
}

int main(int argc, char *argv[]) {
    if (argc != 5) {
        fprintf(stderr, "Usage: %s --port <port> --folder <folder>\n", argv[0]);
        return 1;
    }

    int port = atoi(argv[2]);
    const char *folder = argv[4];

    int server_socket = socket(AF_INET, SOCK_STREAM, 0);
    struct sockaddr_in server_addr;
    server_addr.sin_family = AF_INET;
    server_addr.sin_addr.s_addr = INADDR_ANY;
    server_addr.sin_port = htons(port);

    bind(server_socket, (struct sockaddr *)&server_addr, sizeof(server_addr));
    listen(server_socket, 5);

    printf("Server running on port %d, serving files from %s\n", port, folder);

    while (1) {
        int client_socket = accept(server_socket, NULL, NULL);
        handle_request(client_socket, folder);
        close(client_socket);
    }

    close(server_socket);
    return 0;
}
