#include <iostream>
#include "Utils/httplib.h"
#include "Utils/Utils.h"
#include "KNCenter.h"
using namespace HttpLib;
//#pragma comment( linker, "/subsystem:\"windows\" /entry:\"mainCRTStartup\"" )
/*
Extension	MIME Type
css         text/css
mpga        audio/mpeg
csv	        text/csv
weba	    audio/webm
txt	        text/plain
wav	        audio/wave
vtt	        text/vtt
otf	        font/otf
html,htm	text/html
ttf	        font/ttf
apng	    image/apng
woff	    font/woff
avif	    image/avif
woff2	    font/woff2
bmp	        image/bmp
7z	        application/x-7z-compressed
gif	        image/gif
atom	    application/atom+xml
png	        image/png
pdf	        application/pdf
svg	        image/svg+xml
mjs,js	    application/javascript
webp	    image/webp
json	    application/json
ico	        image/x-icon
rss	        application/rss+xml
tif	        image/tiff
tar	        application/x-tar
tiff	    image/tiff
xhtml,xht	application/xhtml+xml
jpeg,jpg	image/jpeg
xslt	    application/xslt+xml
mp4	        video/mp4
xml	        application/xml
mpeg	    video/mpeg
gz	        application/gzip
webm	    video/webm
zip	        application/zip
mp3	        audio/mp3
wasm	    application/wasm
*/
//http://180.172.204.86:8080/
//http://127.0.0.1:8080/
bool functionTakingLambda(std::string msg, std::function<bool(int columns, char** colData, char** colNames, sqlite3_stmt* stmt)> callback) {
	printf("..%s\n", msg.c_str());
	return callback(0, 0, 0, 0);
}
std::string ConvertChineseToEnglish(std::string str)
{
	auto json = StringHelper::Format(R"({"model":"llama3.1","messages":[{"role":"user","content":"将下面的内容翻译成英文,你只需要输出翻译结果:%s"}],"stream":true})", str.c_str());

	HttpLib::Client cli("http://127.0.0.1:11434/api/chat");
	cli.Head("Content-Type: application/text\r\n");
	auto result = cli.Post(Convert::AnsiToUtf8(json));
	return result.value().body;
}
int main()
{
	KNCenter center;
	auto user = center.GetUser("admin");
	if (!user)
	{
		user = center.CreateUser("admin", "kkpadmin1", 0, 0, 0xFFFFFFFFFFFFFFFF, { 1,2,3,4,5,6,7,15117,75689 });
	}
	center.CreateCardType("M1月卡", "M1M", 30 * 24 * 3600, "M1月卡", "M1_Super.dll");
	auto cType = center.GetCardType("M1月卡");

	auto card = center.CreateCard(user->Id, cType->Id, "测试");

	center.UpdateFile("M1_Super.dll", File::ReadAllBytes(R"(D:\Projects\SCUMX\x64\Release\SCUMX.vmp.dll)"));
	auto f = center.GetFile("M1_Super.dll");
	auto statue = center.CheckCard(card, "HARD_TEST_001");
	auto cards = center.GetAllCard();
	printf(".");


	Server svr;
	//FileServer
	{
		//        svr.Get("/",
		//            [&](const Request& req, Response& res)
		//            {
		//                DirectoryInfo dir = DirectoryInfo("Files");
		//                if (!dir.Exists())
		//                {
		//                    dir.Create();
		//                }
		//                auto files = dir.GetFiles();
		//                StringBuilder sb = StringBuilder();
		//                sb.Append("<html>\n");
		//                sb.Append("<head>\n");
		//                sb.Append("<meta charset=\"UTF-8\">\n");
		//                sb.Append((char*)u8"<title>文件服务</title>\n");
		//
		//                sb.Append(R"(
		//    <style>
		//        #fileContainer {
		//            left: 10;
		//            right: 10;
		//            height: 200px;
		//            overflow-y: auto;
		//            border: 1px solid #ccc;
		//        }
		//        progress {
		//            visibility: hidden;
		//        }
		//        
		//    </style>
		//)");
		//
		//                sb.Append("</head>\n");
		//                sb.Append("<body>\n");
		//                sb.Append((char*)u8"<h1>文件列表</h1>\n");
		//                sb.Append("<ul>\n");
		//                sb.Append("<div id=\"fileContainer\">\n");
		//                for (auto f : files)
		//                {
		//                    auto u8str = Convert::AnsiToUtf8(f.Name());
		//                    sb.Append(StringHelper::Format((const char*)u8"<li><a href=\"DownLoadBin?filename=%s\">%s</a></li>\n", u8str.c_str(), u8str.c_str()));
		//                }
		//                sb.Append("</ul>\n");
		//                sb.Append("</div>\n");
		//
		//                sb.Append((char*)u8"<h1>上传文件</h1>\n");
		//                sb.Append((char*)u8"<progress id=\"progressBar\" value=\"0\" max=\"100\"></progress>\n");
		//                sb.Append((char*)u8"<p></p>\n");
		//                sb.Append((char*)u8"<input type=\"file\" id=\"fileInput\">\n");
		//                sb.Append((char*)u8"<button onclick=\"uploadFile()\">上传</button>\n");
		//
		//                sb.Append((char*)u8R"(
		//    <script>
		//        function uploadFile() {
		//            const fileInput = document.getElementById("fileInput");
		//            const file = fileInput.files[0];
		//            const progressBar = document.getElementById("progressBar");
		//            if (!file) {
		//                alert("请选择文件再上传！");
		//                return;
		//            }
		//            progressBar.style.visibility = 'visible';
		//            const xhr = new XMLHttpRequest();
		//            xhr.open("POST", "/UpLoadBin", true);
		//
		//            xhr.upload.onprogress = function(event) {
		//                if (event.lengthComputable) {
		//                    const percent = (event.loaded / event.total) * 100;
		//                    progressBar.value = percent;
		//                    console.log(`上传进度：${percent}%`);
		//                }
		//            };
		//            xhr.onload = function() {
		//                progressBar.style.visibility = 'hidden';
		//                if (xhr.status === 200) {
		//                    window.alert("文件上传成功！");
		//                    location.reload();
		//                } else {
		//                    window.alert("文件上传失败。返回状态码：" + xhr.status);
		//                }
		//            };
		//            const formData = new FormData();
		//            formData.append("file", file);
		//            xhr.send(formData);
		//        }
		//    </script>
		//)");
		//
		//                sb.Append("</body>\n");
		//                sb.Append("</html>");
		//                res.set_content(sb.ToString(), "text/html");
		//                printf("%s\t获取列表 IP:%s\n", DateTime::Now().ToString().c_str(), req.remote_addr.c_str());
		//            });
		svr.Get("/UpLoadBase64",
			[&](const Request& req, Response& res)
			{
				std::string fname = req.get_param_value("filename");
				std::string data = req.get_param_value("data");
				if (fname.size() > 0 && data.size() > 0)
				{
					File::WriteAllBytes("Files\\" + fname, Convert::FromBase64ToBytes(data));
					res.set_content("OK", "text/plain");
					printf("%s\t文件上传【%s】IP:%s\n", DateTime::Now().ToString().c_str(), fname.c_str(), req.remote_addr.c_str());
				}
				else
				{
					res.set_content("ERROR", "text/plain");
				}
			});
		svr.Get("/DownLoadBase64",
			[&](const Request& req, Response& res)
			{
				std::string fname = req.get_param_value("filename");
				if (fname.size() > 0 && File::Exists("Files\\" + fname))
				{
					res.set_content(Convert::ToBase64(File::ReadAllBytes("Files\\" + fname)), "text/plain");
					printf("%s\t文件下载【%s】IP:%s\n", DateTime::Now().ToString().c_str(), fname.c_str(), req.remote_addr.c_str());
				}
				else
				{
					res.set_content("ERROR", "text/plain");
				}
			});
		svr.Get("/DownLoadBin",
			[&](const Request& req, Response& res)
			{

				std::string fname = req.get_param_value("filename");
				if (fname.size() > 0)
				{
					fname = Convert::Utf8ToAnsi(fname);
				}
				if (fname.size() > 0 && File::Exists("Files\\" + fname))
				{
					FileInfo fi = FileInfo("Files\\" + fname);
					auto bytes = File::ReadAllBytes("Files\\" + fname);
					res.set_header("Content-Disposition", StringHelper::Format("attachment; filename=%s;", fname.c_str()));
					if (StringHelper::Contains(StringHelper::ToLower(fi.Extension()), "mp3"))
						res.set_content((char*)bytes.data(), bytes.size(), "video/mp3");
					else if (StringHelper::Contains(StringHelper::ToLower(fi.Extension()), "gif"))
						res.set_content((char*)bytes.data(), bytes.size(), "video/gif");
					else if (StringHelper::Contains(StringHelper::ToLower(fi.Extension()), "mp4"))
						res.set_content((char*)bytes.data(), bytes.size(), "video/mp4");
					else if (StringHelper::Contains(StringHelper::ToLower(fi.Extension()), "jpg"))
						res.set_content((char*)bytes.data(), bytes.size(), "image/jpeg");
					else if (StringHelper::Contains(StringHelper::ToLower(fi.Extension()), "png"))
						res.set_content((char*)bytes.data(), bytes.size(), "image/png");
					else if (StringHelper::Contains(StringHelper::ToLower(fi.Extension()), "wav"))
						res.set_content((char*)bytes.data(), bytes.size(), "audio/wave");
					else
					{
						res.set_content((char*)bytes.data(), bytes.size(), "");
					}
					//wav	        audio/wave
					printf("%s\t文件下载【%s】IP:%s\n", DateTime::Now().ToString().c_str(), fname.c_str(), req.remote_addr.c_str());
				}
				else
				{
					res.set_content("ERROR", "text/plain");
				}
			});
		svr.Post("/UpLoadBin",
			[&](const Request& req, Response& res, const ContentReader& content_reader)
			{
				if (req.is_multipart_form_data())
				{
					FileStream* fs = NULL;
					MultipartFormDataItems files;
					content_reader(
						[&](const MultipartFormData& file)
						{
							files.push_back(file);
							auto ansiStr = Convert::Utf8ToAnsi(file.filename);
							printf("%s\t文件上传【%s】IP:%s\n", DateTime::Now().ToString().c_str(), ansiStr.c_str(), req.remote_addr.c_str());
							FileInfo fi = FileInfo("Files\\" + ansiStr);
							DirectoryInfo dir = DirectoryInfo(fi.DirectoryName());
							if (!dir.Exists())
								dir.Create();
							fs = new FileStream("Files\\" + ansiStr, FileMode::Write);
							return true;
						},
						[&](const char* data, size_t data_length)
						{
							files.back().content.append(data, data_length);
							if (fs)
								fs->Write(data, data_length);
							return true;
						});
					fs->Close();
					delete fs;
				}
				else
				{
					std::string body;
					content_reader([&](const char* data, size_t data_length) {
						body.append(data, data_length);
						return true;
						});
				}
			});
	}

	svr.set_error_handler([](const auto& req, auto& res) {
		auto fmt = "<p>Error Status: <span style='color:red;'>%d</span></p>";
		char buf[BUFSIZ];
		snprintf(buf, sizeof(buf), fmt, res.status);
		res.set_content(buf, "text/html");
		});
	svr.set_exception_handler([](const auto& req, auto& res, std::exception_ptr ep) {
		auto fmt = "<h1>Error 500</h1><p>%s</p>";
		char buf[BUFSIZ];
		try {
			std::rethrow_exception(ep);
		}
		catch (std::exception& e) {
			snprintf(buf, sizeof(buf), fmt, e.what());
		}
		catch (...) {
			snprintf(buf, sizeof(buf), fmt, "Unknown Exception");
		}
		res.set_content(buf, "text/html");
		res.status = StatusCode::InternalServerError_500;
		});
	svr.listen("0.0.0.0", 8088);
}