#include "curl_utils.h"
#include <chrono>

// 回调函数，用于处理从服务器接收到的数据
size_t WriteCallback(void* contents, size_t size, size_t nmemb, std::string* userp) {
	size_t totalSize = size * nmemb;
	userp->append((char*)contents, totalSize);
	return totalSize;
}

// 回调函数，用于处理接收到的响应头
size_t HeaderCallback(char* buffer, size_t size, size_t nitems, void* userdata) {
	HeaderData* headerData = static_cast<HeaderData*>(userdata);
	std::string header(buffer, size * nitems);
	if (!headerData->found && header.find("x-csrf-token:") == 0) {
		size_t colonPos = header.find(':');
		if (colonPos != std::string::npos) {
			headerData->value = header.substr(colonPos + 1);
			headerData->value.erase(0, headerData->value.find_first_not_of(" \t"));
			headerData->value.erase(headerData->value.length() - 2);
			headerData->found = true; // 标记为已找到
		}
	}

	return size * nitems;
}

vector<string> split_regex(const string& str, const string& pattern) {
	vector<string> tokens;
	regex rgx(pattern);
	sregex_token_iterator iter(str.begin(), str.end(), rgx, -1);
	sregex_token_iterator end;
	while (iter != end) {
		tokens.push_back(*iter++);
	}
	return tokens;
}

string URLEncodeFTPPath2(const std::string& path) {
	CURL* curl = curl_easy_init();
	if (!curl) return path;

	std::string result;
	std::string encoded_part;

	// 分割路径，分别编码每个部分
	size_t start = 0;
	size_t end = path.find('/');

	while (end != std::string::npos) {
		std::string part = path.substr(start, end - start);
		if (!part.empty()) {
			char* encoded = curl_easy_escape(curl, part.c_str(), part.length());
			if (encoded) {
				result += encoded;
				curl_free(encoded);
			}
			else {
				result += part;
			}
		}
		result += '/';
		start = end + 1;
		end = path.find('/', start);
	}

	// 最后一部分
	if (start < path.length()) {
		std::string part = path.substr(start);
		char* encoded = curl_easy_escape(curl, part.c_str(), part.length());
		if (encoded) {
			result += encoded;
			curl_free(encoded);
		}
		else {
			result += part;
		}
	}

	curl_easy_cleanup(curl);
	return result;
}

// 写入回调函数（用于上传文件）
size_t read_callback(void* ptr, size_t size, size_t nmemb, FILE* stream) {
	size_t retcode = fread(ptr, size, nmemb, stream);
	return retcode;
}

int sendFileByFtp(string ftp_url, string file_path, string file_dir, string user, string pwd)
{
	int result = 0;
	CURL* curl;
	CURLcode res;

	// 初始化libcurl
	curl_global_init(CURL_GLOBAL_DEFAULT);
	curl = curl_easy_init();

	if (curl) {
		string encoded_ftp_url = URLEncodeFTPPath2(ftp_url);
		// 1. 创建远程目录
		curl_easy_setopt(curl, CURLOPT_URL, encoded_ftp_url.c_str());
		curl_easy_setopt(curl, CURLOPT_USERNAME, user.c_str());
		curl_easy_setopt(curl, CURLOPT_PASSWORD, pwd.c_str());
		curl_easy_setopt(curl, CURLOPT_FTP_CREATE_MISSING_DIRS, CURLFTP_CREATE_DIR);

		// 重要：对于非标准端口，可能需要额外设置
		curl_easy_setopt(curl, CURLOPT_FTPPORT, "-");  // 被动模式
		curl_easy_setopt(curl, CURLOPT_FTP_USE_EPSV, 0L);  // 禁用 EPSV

		// 启用详细日志查看具体问题
		curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);

		// 设置超时
		curl_easy_setopt(curl, CURLOPT_TIMEOUT, 30L);
		curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 10L);

		// 执行目录创建
		res = curl_easy_perform(curl);
		if (res != CURLE_OK) {
			WriteLog("FTP 创建目录失: %s (错误: %d)\n",
				curl_easy_strerror(res), res);
			result = 1;
			goto end;
		}

		// 2. 上传文件到新目录
		FILE* file = nullptr;
		errno_t err = fopen_s(&file, file_path.c_str(), "rb");
		if (err != 0 || file == nullptr) {
			// 处理错误
			WriteLog("无法打开本地文件>%s\n", file_path.c_str());
			result = 1;
			goto end;
		}
		//FILE* file = fopen(file_path.c_str(), "rb");
		//if (!file) {
		//	WriteLog("无法打开本地文件>%s\n", file_path.c_str());
		//	result = 1;
		//	goto end;
		//}

		// 设置FTP上传选项
		curl_easy_setopt(curl, CURLOPT_UPLOAD, 1L);
		curl_easy_setopt(curl, CURLOPT_URL, file_dir.c_str());
		curl_easy_setopt(curl, CURLOPT_READFUNCTION, read_callback);
		curl_easy_setopt(curl, CURLOPT_READDATA, file);

		// 获取文件大小
		fseek(file, 0, SEEK_END);
		curl_off_t file_size = ftell(file);
		fseek(file, 0, SEEK_SET);
		curl_easy_setopt(curl, CURLOPT_INFILESIZE_LARGE, file_size);

		// 执行文件上传
		res = curl_easy_perform(curl);
		if (res != CURLE_OK) {
			WriteLog("上传文件失败:%s\n", curl_easy_strerror(res));
			result = 1;
		}
		else {
			WriteLog("文件上传成功\n");
		}

		fclose(file);
		curl_easy_cleanup(curl);
	}

end:
	curl_global_cleanup();
	return result;
}

string postJSON(string url, string body, long& http_code, string& error)
{
	string response_data = "";
	CURL* curl;
	CURLcode res;
	// 初始化 libcurl 会话
	curl_global_init(CURL_GLOBAL_DEFAULT);
	curl = curl_easy_init();

	if (curl) {
		// 设置要访问的 URL
		curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "POST");
		curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
		curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
		curl_easy_setopt(curl, CURLOPT_DEFAULT_PROTOCOL, "http");
		curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);
		curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L);

		// 设置请求头
		struct curl_slist* headers = NULL;
		headers = curl_slist_append(headers, "Content-Type: application/json; charset=UTF-8");
		curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
		curl_easy_setopt(curl, CURLOPT_POSTFIELDS, body.c_str());
		curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, body.size());

		// 设置回调函数以接收响应数据
		curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback);
		curl_easy_setopt(curl, CURLOPT_WRITEDATA, &response_data);

		// 执行请求
		res = curl_easy_perform(curl);

		// 检查错误
		if (res != CURLE_OK)
		{
			error = curl_easy_strerror(res);

		}
		curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &http_code);
		// 清理资源
		curl_slist_free_all(headers);
		curl_easy_cleanup(curl);
	}
	// 清理全局环境
	curl_global_cleanup();

	return response_data;
}

// URL 编码函数（处理空格等特殊字符）
std::string URLEncodeFTPPath(const std::string& path) {
    CURL* curl = curl_easy_init();
    if (!curl) return path;

    std::string result;
    std::string encoded_part;

    // 分割路径，分别编码每个部分
    size_t start = 0;
    size_t end = path.find('/');

    while (end != std::string::npos) {
        std::string part = path.substr(start, end - start);
        if (!part.empty()) {
            char* encoded = curl_easy_escape(curl, part.c_str(), part.length());
            if (encoded) {
                result += encoded;
                curl_free(encoded);
            }
            else {
                result += part;
            }
        }
        result += '/';
        start = end + 1;
        end = path.find('/', start);
    }

    // 最后一部分
    if (start < path.length()) {
        std::string part = path.substr(start);
        char* encoded = curl_easy_escape(curl, part.c_str(), part.length());
        if (encoded) {
            result += encoded;
            curl_free(encoded);
        }
        else {
            result += part;
        }
    }

    curl_easy_cleanup(curl);
    return result;
}

bool TestBasicFTPConnection() {
    CURL* curl = curl_easy_init();
    if (!curl) return false;

    // 最简单的测试 - 只连接到根目录
    std::string test_url = "ftp://192.168.120.92:22/";

    WriteLog("测试基础连接: %s\n", test_url.c_str());

    curl_easy_setopt(curl, CURLOPT_URL, test_url.c_str());
    curl_easy_setopt(curl, CURLOPT_USERNAME, "ftp1");
    curl_easy_setopt(curl, CURLOPT_PASSWORD, "Jd@tc00"); // 需要密码

    // 只连接，不执行任何操作
    curl_easy_setopt(curl, CURLOPT_NOBODY, 1L);

    // 启用详细日志
    curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);

    CURLcode res = curl_easy_perform(curl);

    if (res != CURLE_OK) {
        WriteLog("基础连接失败: %s (错误: %d)\n",
            curl_easy_strerror(res), res);
    }
    else {
        WriteLog("基础连接成功\n");
    }

    curl_easy_cleanup(curl);
    return (res == CURLE_OK);
}

bool UploadToFTPWithDebug() {
    // 你的参数
    std::string server = "192.168.120.92";
    int port = 22;
    std::string username = "ftp1";
    std::string password = "Jd@tc00";
    std::string remote_dir = "DocumentRevision/MS WordX/WD00000644-10";
    std::string filename = "WD00000644_ceshiwen.docx";
    std::string local_file = "C:\\Users\\ADMINI~1\\AppData\\Local\\Temp\\2\\WD00000644_ceshiwen.docx";

    WriteLog("=== FTP 上传调试开始 ===\n");
    WriteLog("服务器: %s:%d\n", server.c_str(), port);
    WriteLog("用户名: %s\n", username.c_str());
    WriteLog("本地文件: %s\n", local_file.c_str());
    WriteLog("远程目录: %s\n", remote_dir.c_str());
    WriteLog("文件名: %s\n", filename.c_str());

    // 1. 先测试基础连接
    if (!TestBasicFTPConnection()) {
        WriteLog("基础连接测试失败，请检查网络和凭据\n");
        return false;
    }

    // 2. 创建目录
    CURL* curl_dir = curl_easy_init();
    if (curl_dir) {
        // 构建目录URL - 特别注意空格的处理
        std::string dir_path = remote_dir;

        // 方法1：直接使用路径（libcurl 会自动处理空格）
        std::string dir_url = "ftp://" + server + ":" + std::to_string(port) + "/" + dir_path + "/";

        WriteLog("尝试创建目录，URL: %s\n", dir_url.c_str());

        curl_easy_setopt(curl_dir, CURLOPT_URL, dir_url.c_str());
        curl_easy_setopt(curl_dir, CURLOPT_USERNAME, username.c_str());
        curl_easy_setopt(curl_dir, CURLOPT_PASSWORD, password.c_str());
        curl_easy_setopt(curl_dir, CURLOPT_FTP_CREATE_MISSING_DIRS, CURLFTP_CREATE_DIR);

        // 重要：设置 FTP 选项
        curl_easy_setopt(curl_dir, CURLOPT_FTPPORT, "-");  // 被动模式
        curl_easy_setopt(curl_dir, CURLOPT_FTP_USE_EPSV, 0L);  // 禁用 EPSV

        // 设置超时
        curl_easy_setopt(curl_dir, CURLOPT_TIMEOUT, 30L);
        curl_easy_setopt(curl_dir, CURLOPT_CONNECTTIMEOUT, 10L);

        // 启用详细日志
        curl_easy_setopt(curl_dir, CURLOPT_VERBOSE, 1L);

        CURLcode res = curl_easy_perform(curl_dir);

        if (res != CURLE_OK) {
            WriteLog("目录创建失败: %s (错误: %d)\n",
                curl_easy_strerror(res), res);

            // 尝试另一种方法：手动编码
            std::string encoded_dir = URLEncodeFTPPath(dir_path);
            std::string dir_url2 = "ftp://" + server + ":" + std::to_string(port) + "/" + encoded_dir + "/";

            WriteLog("尝试方法2，编码URL: %s\n", dir_url2.c_str());

            // 重置并重试
            curl_easy_reset(curl_dir);
            curl_easy_setopt(curl_dir, CURLOPT_URL, dir_url2.c_str());
            curl_easy_setopt(curl_dir, CURLOPT_USERNAME, username.c_str());
            curl_easy_setopt(curl_dir, CURLOPT_PASSWORD, password.c_str());
            curl_easy_setopt(curl_dir, CURLOPT_FTP_CREATE_MISSING_DIRS, CURLFTP_CREATE_DIR);
            curl_easy_setopt(curl_dir, CURLOPT_FTPPORT, "-");
            curl_easy_setopt(curl_dir, CURLOPT_VERBOSE, 1L);

            res = curl_easy_perform(curl_dir);

            if (res != CURLE_OK) {
                WriteLog("方法2也失败: %s\n", curl_easy_strerror(res));
            }
        }
        else {
            WriteLog("目录创建成功\n");
        }

        curl_easy_cleanup(curl_dir);
    }

    // 3. 上传文件
    CURL* curl_upload = curl_easy_init();
    if (!curl_upload) {
        WriteLog("初始化上传CURL失败\n");
        return false;
    }

    // 打开本地文件
    FILE* file = nullptr;
    errno_t err = fopen_s(&file, local_file.c_str(), "rb");
    if (err != 0 || file == nullptr) {
        // 处理错误
        WriteLog("无法打开本地文件>%s\n", local_file.c_str());
        curl_easy_cleanup(curl_upload);
        return false;
    }

    // 获取文件大小
    fseek(file, 0, SEEK_END);
    long file_size = ftell(file);
    fseek(file, 0, SEEK_SET);

    WriteLog("文件大小: %ld bytes\n", file_size);

    // 构建上传URL
    std::string upload_path = remote_dir + "/" + filename;
    std::string upload_url = "ftp://" + server + ":" + std::to_string(port) + "/" + upload_path;

    WriteLog("上传URL: %s\n", upload_url.c_str());

    // 设置上传选项
    curl_easy_setopt(curl_upload, CURLOPT_URL, upload_url.c_str());
    curl_easy_setopt(curl_upload, CURLOPT_USERNAME, username.c_str());
    curl_easy_setopt(curl_upload, CURLOPT_PASSWORD, password.c_str());
    curl_easy_setopt(curl_upload, CURLOPT_UPLOAD, 1L);
    curl_easy_setopt(curl_upload, CURLOPT_READDATA, file);
    curl_easy_setopt(curl_upload, CURLOPT_INFILESIZE_LARGE, (curl_off_t)file_size);

    // FTP 特定选项
    curl_easy_setopt(curl_upload, CURLOPT_FTPPORT, "-");  // 被动模式
    curl_easy_setopt(curl_upload, CURLOPT_FTP_CREATE_MISSING_DIRS, CURLFTP_CREATE_DIR);

    // 设置超时
    curl_easy_setopt(curl_upload, CURLOPT_TIMEOUT, 60L);

    // 启用详细日志
    curl_easy_setopt(curl_upload, CURLOPT_VERBOSE, 1L);

    // 执行上传
    CURLcode res = curl_easy_perform(curl_upload);

    // 关闭文件
    fclose(file);

    if (res != CURLE_OK) {
        WriteLog("上传失败: %s (错误: %d)\n",
            curl_easy_strerror(res), res);

        // 尝试使用编码的URL
        std::string encoded_upload_path = URLEncodeFTPPath(upload_path);
        std::string upload_url2 = "ftp://" + server + ":" + std::to_string(port) + "/" + encoded_upload_path;

        WriteLog("尝试编码URL上传: %s\n", upload_url2.c_str());

        
        //file = fopen(local_file.c_str(), "rb");
        // 重新打开文件
        errno_t err = fopen_s(&file, local_file.c_str(), "rb");
        if (err != 0 || file == nullptr) {
            // 处理错误
            WriteLog("重新打开文件无法打开本地文件>%s\n", local_file.c_str());
            curl_easy_cleanup(curl_upload);
            return false;
        }
        if (file) {
            curl_easy_reset(curl_upload);

            curl_easy_setopt(curl_upload, CURLOPT_URL, upload_url2.c_str());
            curl_easy_setopt(curl_upload, CURLOPT_USERNAME, username.c_str());
            curl_easy_setopt(curl_upload, CURLOPT_PASSWORD, password.c_str());
            curl_easy_setopt(curl_upload, CURLOPT_UPLOAD, 1L);
            curl_easy_setopt(curl_upload, CURLOPT_READDATA, file);
            curl_easy_setopt(curl_upload, CURLOPT_INFILESIZE_LARGE, (curl_off_t)file_size);
            curl_easy_setopt(curl_upload, CURLOPT_FTPPORT, "-");
            curl_easy_setopt(curl_upload, CURLOPT_VERBOSE, 1L);

            res = curl_easy_perform(curl_upload);
            fclose(file);
        }
    }

    if (res == CURLE_OK) {
        WriteLog("=== 文件上传成功 ===\n");
        WriteLog("文件已上传到: %s\n", upload_url.c_str());
    }
    else {
        WriteLog("=== 文件上传失败 ===\n");
        WriteLog("最终错误: %s\n", curl_easy_strerror(res));
    }

    curl_easy_cleanup(curl_upload);
    return (res == CURLE_OK);
}

void CheckCurlFeatures() {
    curl_version_info_data* version_info = curl_version_info(CURLVERSION_NOW);

    WriteLog("=== libcurl 功能检查 ===\n");
    WriteLog("libcurl 版本: %s\n", version_info->version);
    WriteLog("支持的协议:\n");

    // 检查协议支持
    if (version_info->protocols) {
        for (int i = 0; version_info->protocols[i]; i++) {
            WriteLog("  - %s\n", version_info->protocols[i]);
        }
    }

    // 检查特定协议
    bool supports_ftp = false;
    bool supports_sftp = false;

    for (int i = 0; version_info->protocols[i]; i++) {
        if (strcmp(version_info->protocols[i], "ftp") == 0) {
            supports_ftp = true;
        }
        if (strcmp(version_info->protocols[i], "sftp") == 0) {
            supports_sftp = true;
        }
    }

    WriteLog("\nFTP 支持: %s\n", supports_ftp ? "是" : "否");
    WriteLog("SFTP 支持: %s\n", supports_sftp ? "是" : "否");

    if (!supports_ftp && !supports_sftp) {
        WriteLog("错误: libcurl 没有编译 FTP/SFTP 支持！\n");
        WriteLog("需要重新编译 libcurl 或使用支持 FTP 的版本\n");
    }
}