#include "kvstore.h"
#include "kvs_rw_tools.h"
#include "mem_pool/mem_pool.h"
#include <arpa/inet.h>
#include <fcntl.h>
#include <unistd.h>

int init_cmd_log(const char *file, int *logfd){
	if(!file) return -1;
	int fd = open(file, O_RDWR | O_CREAT | O_APPEND, 0644);
	if(fd < 0) return -2;

	*logfd = fd;
	return 0;
}

int destroy_cmd_log(int logfd){
    fsync(logfd);
	close(logfd);
	return 0;
}



int kvs_save_cmd_to_logfile(const uint8_t *cmd, size_t len, int logfd){
	if (logfd < 0 || !cmd || len == 0)
        return -1;

    if (len > UINT32_MAX)
        return -2;

    uint32_t nlen = htonl((uint32_t)len);

    if (write_full(logfd, &nlen, sizeof(nlen)) < 0)
        return -3;

    if (write_full(logfd, cmd, len) < 0)
        return -4;

	return 0;
}

int	kvs_replay_log(const char *logfile, int logfd){
	 if (!logfile|| logfd<0) return -1;

    for (;;) {
        uint32_t nlen = 0;

        int hr = read_full(logfd, &nlen, sizeof(nlen));
        if (hr == 0) break;          /* EOF：正常结束 */
        if (hr < 0) { return -2; }  /* 半截头 */

        uint32_t len = ntohl(nlen);
        if (len == 0) { return -3; }

        uint8_t *cmd = (uint8_t *)kvs_malloc(len);
        if (!cmd) { return -5; }

        int pr = read_full(logfd, cmd, len);
        if (pr <= 0) { /* 半截 payload */
            kvs_free(cmd);
            return -6;
        }

        kvs_req_t req;
        memset(&req, 0, sizeof(req));

        int clen = kvs_parse_one_cmd(cmd, (int)len, &req);
        if (clen <= 0 || clen != (int)len) {
            kvs_free_request(&req);
            kvs_free(cmd);
            return -7;
        }

        kvs_rsp_t rsp;
        memset(&rsp, 0, sizeof(rsp));

        if (kvs_execute_one_cmd(&req, &rsp) < 0) {
            kvs_free_request(&req);
            kvs_free(cmd);
            return -8;
        }

        kvs_free_request(&req);
        kvs_free(cmd);
    }

    return 0;
}

/**
 * clear log file not close
 */
int ksv_clear_log(int logfd){
	if(logfd < 0) return -1;
	ftruncate(logfd, 0);
	lseek(logfd, 0, SEEK_SET);
	return 0;
}