#ifndef COMMON_H
#define COMMON_H

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <stdint.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <pthread.h>

// ─── Work-Queue (client-side, thread-safe) ───────────────────────────────────

typedef struct file_task {
    char full_path[2048];
    char rel_path[2048];
    uint64_t file_size;
    uint64_t checksum;
    struct file_task *next;
} file_task_t;

typedef struct {
    file_task_t   *head;
    file_task_t   *tail;
    int            done;       // set to 1 when scanner is finished
    int            error;      // set to 1 on fatal scan error
    pthread_mutex_t lock;
    pthread_cond_t  cond;
} work_queue_t;

void wq_init(work_queue_t *q);
void wq_push(work_queue_t *q, const char *full_path, const char *rel_path, uint64_t file_size, uint64_t checksum);
file_task_t *wq_pop(work_queue_t *q);   // blocks until item or done
void wq_finish(work_queue_t *q);
void wq_destroy(work_queue_t *q);

// ─── Worker-thread argument (client-side) ────────────────────────────────────

typedef struct {
    int            thread_id;
    work_queue_t  *queue;
    const char    *host;
    int            port;
    int            use_udp;
    int            result;     // 0 = ok, -1 = error
} worker_arg_t;


#define DEFAULT_PORT 8082

// Protocol Magics
#define MAGIC_META        0x53594E43 // 'SYNC'
#define MAGIC_BATCH_META  0x42415443 // 'BATC' - Batch metadata
#define MAGIC_DONE        0x444F4E45 // 'DONE'
#define MAGIC_VERIFY     0x56455259 // 'VERY'
#define MAGIC_UDP_REQ    0x55445052 // 'UDPR'

// Batch constants
#define BATCH_MAX_FILES  64  // Max files per batch


// Response Codes
#define RESP_SEND_DATA 1
#define RESP_SKIP      2
#define RESP_ERROR     0
#define RESP_OK        3
#define RESP_USE_UDP   4

// UDP Constants
#define UDP_PAYLOAD_MAX 1400
#define MAGIC_UDP_DATA  0x55445044 // 'UDPD'
#define MAGIC_UDP_KNOCK 0x5544504B // 'UDPK'

#pragma pack(push, 1)
typedef struct {
    uint32_t magic;
    uint32_t name_len;
    uint64_t file_size;
    uint32_t mode;
    uint64_t checksum;
} file_meta_t;

// Batch metadata: header followed by N file_meta_t + name strings
typedef struct {
    uint32_t magic;           // MAGIC_BATCH_META
    uint32_t count;           // Number of files in batch
    uint32_t total_name_len;  // Total length of all filenames combined
    uint64_t total_size;      // Total size of all files
} batch_meta_header_t;

typedef struct {
    uint32_t response;
    uint32_t file_id;          // For single file
    uint32_t reserved[2];
} file_response_t;

// Batch response: one response code for the whole batch
typedef struct {
    uint32_t magic;            // MAGIC_BATCH_META (echoed back)
    uint32_t count;            // Number of files accepted
    uint32_t first_file_id;    // First file_id in this batch
} batch_response_t;


typedef struct {
    uint32_t udp_port;
    uint64_t session_id;
} udp_handshake_t;

typedef struct {
    uint32_t magic;
    uint64_t session_id;
    uint32_t file_id;
    uint32_t block_id;
    uint64_t block_offset;
    uint32_t payload_len;
} udp_packet_header_t;
#pragma pack(pop)


// Socket Helpers
ssize_t readn(int fd, void *vptr, size_t n);
ssize_t writen(int fd, const void *vptr, size_t n);

// Directory/File Helpers
int make_path(const char *path, mode_t mode);

#endif // COMMON_H
