//% color="#1e90ff" iconWidth=50 iconHeight=40
namespace doubao {
    
    //% block="初始化API密钥[api_psd]接入点ID[id_psd]温度[temp]" blockType="command"
    //% api_psd.shadow="string" api_psd.defl=c4a347fc-b9f9-4be6-96f5-b3334abf9016
    //% id_psd.shadow="string" id_psd.defl=ep-20250624120313-pt5n6
    //% temp.shadow="number" temp.defl=0.3
    export function myBlock3(parameter: any, block: any) {
        let api_psd = parameter.api_psd.code
        let id_psd = parameter.id_psd.code
        let temp = parameter.temp.code
        
        // 添加必要的头文件
        Generator.addInclude("HTTPClient", `#include <HTTPClient.h>`)
        Generator.addInclude("ArduinoJsonK10", `#include <ArduinoJsonK10.h>`)
        Generator.addInclude("k10_base64", `#include "k10_base64.h"`)
        Generator.addInclude("WiFiClientSecure", `#include <WiFiClientSecure.h>`)
        
        // 添加配置对象
        Generator.addObject("doubao_apiKey", `const char*`, `doubao_apiKey = ${api_psd};  // API密钥`)
        Generator.addObject("apiUrl", `const String`, `apiUrl = "https://ark.cn-beijing.volces.com/api/v3/chat/completions";  // API地址`)
        Generator.addObject("model", `const String`, `model = ${id_psd};  // 使用的模型`)
        Generator.addObject("temperature", `const float`, `temperature = ${temp};  // AI创造性参数（0-1）`)
        
        // 添加错误码常量
        Generator.addObject("ERROR_NETWORK", `const String`, `ERROR_NETWORK = "<network_error>";`)
        Generator.addObject("ERROR_CAMERA", `const String`, `ERROR_CAMERA = "<camera_error>";`)
        Generator.addObject("ERROR_IMAGE_TOO_LARGE", `const String`, `ERROR_IMAGE_TOO_LARGE = "<image_too_large>";`)
        Generator.addObject("ERROR_INVALID_INPUT", `const String`, `ERROR_INVALID_INPUT = "<invalid_input>";`)
        Generator.addObject("ERROR_JSON_PARSE", `const String`, `ERROR_JSON_PARSE = "<json_parse_error>";`)
        Generator.addObject("ERROR_TIMEOUT", `const String`, `ERROR_TIMEOUT = "<timeout_error>";`)
        
        // 添加全局变量
        Generator.addObject("answer", `String`, `answer;`)
    }
    
    //% block="初始化角色[role]" blockType="command"
    //% role.shadow="string" role.defl=你是人工智能助手，你叫小行
    export function myBlock2(parameter: any, block: any) {
        let role = parameter.role.code
        Generator.addObject("systemPrompt", `const String`, `systemPrompt = ${role};`)
        
        // 添加公用函数
        let validateConfigFunc = [
            'bool validateConfig() {',
            '  if (doubao_apiKey == nullptr || strlen(doubao_apiKey) == 0) {',
            '    Serial.println("错误：API密钥未设置");',
            '    return false;',
            '  }',
            '  if (model.length() == 0) {',
            '    Serial.println("错误：模型ID未设置");',
            '    return false;',
            '  }',
            '  if (temperature < 0.0 || temperature > 1.0) {',
            '    Serial.println("错误：温度参数超出范围(0-1)");',
            '    return false;',
            '  }',
            '  return true;',
            '}',
        ]
        let sendHttpRequestFunc = [
            'String sendHttpRequest(String payload) {',
            '  WiFiClientSecure client;',
            '  String outputText = ERROR_NETWORK;',
            '  client.setInsecure();',
            '  if (!client.connect("ark.cn-beijing.volces.com", 443)) {',
            '    Serial.println("连接服务器失败");',
            '    return ERROR_NETWORK;',
            '  }',
            '  String request = "POST /api/v3/chat/completions HTTP/1.1\\r\\n";',
            '  request += "Host: ark.cn-beijing.volces.com\\r\\n";',
            '  request += "Content-Type: application/json\\r\\n";',
            '  request += "Authorization: Bearer " + String(doubao_apiKey) + "\\r\\n";',
            '  request += "Transfer-Encoding: chunked\\r\\n";',
            '  request += "Connection: close\\r\\n";',
            '  request += "\\r\\n";',
            '  client.print(request);',
            '  int chunkSize = 4096;',
            '  int totalLength = payload.length();',
            '  int sent = 0;',
            '  while (sent < totalLength) {',
            '    int currentChunkSize = min(chunkSize, totalLength - sent);',
            '    String chunk = payload.substring(sent, sent + currentChunkSize);',
            '    String chunkHeader = String(currentChunkSize, HEX) + "\\r\\n";',
            '    client.print(chunkHeader);',
            '    client.print(chunk);',
            '    client.print("\\r\\n");',
            '    sent += currentChunkSize;',
            '    delay(5);',
            '  }',
            '  client.print("0\\r\\n\\r\\n");',
            '  String response = "";',
            '  unsigned long timeout = millis() + 300000;',
            '  while (client.connected() && millis() < timeout) {',
            '    if (client.available()) {',
            '      response += client.readString();',
            '    }',
            '    delay(10);',
            '  }',
            '  client.stop();',
            '  if (response.length() > 0) {',
            '    int jsonStart = response.indexOf("\\r\\n\\r\\n");',
            '    if (jsonStart > 0) {',
            '      response = response.substring(jsonStart + 4);',
            '    }',
            '    DynamicJsonDocument jsonDoc(32768);',
            '    DeserializationError error = deserializeJson(jsonDoc, response);',
            '    if (!error) {',
            '      outputText = jsonDoc["choices"][0]["message"]["content"].as<String>();',
            '      Serial.println("JSON解析成功");',
            '    } else {',
            '      Serial.print("JSON解析错误: ");',
            '      Serial.println(error.c_str());',
            '      outputText = ERROR_JSON_PARSE;',
            '    }',
            '  } else {',
            '    Serial.println("未接收到响应");',
            '    outputText = ERROR_TIMEOUT;',
            '  }',
            '  return outputText;',
            '}',
        ]
        let sendHttpRequestWithRetryFunc = [
            'String sendHttpRequestWithRetry(String payload, int maxRetries = 3) {',
            '  String result;',
            '  for (int i = 0; i < maxRetries; i++) {',
            '    Serial.printf("尝试请求 %d/%d\\n", i + 1, maxRetries);',
            '    result = sendHttpRequest(payload);',
            '    if (result != ERROR_NETWORK && result != ERROR_TIMEOUT) {',
            '      return result;',
            '    }',
            '    if (i < maxRetries - 1) {',
            '      int delayTime = 1000 * (i + 1);',
            '      Serial.printf("请求失败，%d ms后重试\\n", delayTime);',
            '      delay(delayTime);',
            '    }',
            '  }',
            '  return result;',
            '}',
        ]
        let buildPayloadFunc = [
            'String buildPayload(String inputText, String base64Image = "", String imageFormat = "") {',
            '  String payload;',
            '  payload.reserve(2000);',
            '  payload = "{";',
            '  payload += "\\"model\\":\\"" + model + "\\",";',
            '  payload += "\\"messages\\":[";',
            '  payload += "{\\"role\\":\\"system\\",\\"content\\":\\"" + systemPrompt + "\\"},";',
            '  payload += "{";',
            '  payload += "\\"role\\":\\"user\\",";',
            '  payload += "\\"content\\":[";',
            '  if (base64Image != "" && base64Image != "NULL") {',
            '    payload += "{\\"type\\":\\"image_url\\",";',
            '    payload += "\\"image_url\\":{\\"url\\":\\"data:image/" + imageFormat + ";base64," + base64Image + "\\"}},";',
            '  }',
            '  payload += "{\\"type\\":\\"text\\",\\"text\\":\\"" + inputText + "\\"}";',
            '  payload += "]";',
            '  payload += "}";',
            '  payload += "],";',
            '  payload += "\\"temperature\\":" + String(temperature);',
            '  payload += "}";',
            '  return payload;',
            '}'
        ]
        
        Generator.addFunction("validateConfig", "bool", "validateConfig", "", validateConfigFunc)
        Generator.addFunction("sendHttpRequest", "String", "sendHttpRequest", "String payload", sendHttpRequestFunc)
        Generator.addFunction("sendHttpRequestWithRetry", "String", "sendHttpRequestWithRetry", "String payload, int maxRetries", sendHttpRequestWithRetryFunc)
        Generator.addFunction("buildPayload", "String", "buildPayload", "String inputText, String base64Image, String imageFormat", buildPayloadFunc)
    }
    
    //% block="发送消息[msg]" blockType="command"
    //% msg.shadow="string" msg.defl=你好，小行！
    export function myBlock5(parameter: any, block: any) {
        let msg = parameter.msg.code
        
        let func = [
            'String getGPTAnswer(String inputText) {',
            '  if (!validateConfig()) {',
            '    return ERROR_INVALID_INPUT;',
            '  }',
            '  if (inputText.length() == 0) {',
            '    Serial.println("错误：输入文本为空");',
            '    return ERROR_INVALID_INPUT;',
            '  }',
            '  String payload = buildPayload(inputText);',
            '  Serial.printf("发送文本请求，payload长度: %d\\n", payload.length());',
            '  return sendHttpRequestWithRetry(payload);',
            '}'
        ]
        
        Generator.addFunction("getGPTAnswer", "String", "getGPTAnswer", "String inputText", func)
        Generator.addCode(`answer = "";`)
        Generator.addCode(`answer = getGPTAnswer(${msg});`)
    }
    
    //% block="发送消息，文字[msg_urlimg]，图片URL[url_img]" blockType="command"
    //% msg_urlimg.shadow="string" msg_urlimg.defl=图片主要讲了什么?
    //% url_img.shadow="string" url_img.defl=https://ark-project.tos-cn-beijing.volces.com/images/view.jpeg
    export function myBlock6(parameter: any, block: any) {
        let msg_urlimg = parameter.msg_urlimg.code
        let url_img = parameter.url_img.code
        
        let func = [
            'String getGPTAnswer_urlimg(String inputText, String imageUrl = "") {',
            '  if (inputText.length() == 0) {',
            '    Serial.println("错误：输入文本为空");',
            '    return ERROR_INVALID_INPUT;',
            '  }',
            '  String payload;',
            '  payload.reserve(2000);',
            '  payload = "{";',
            '  payload += "\\"model\\":\\"" + model + "\\",";',
            '  payload += "\\"messages\\":[";',
            '  payload += "{\\"role\\":\\"system\\",\\"content\\":\\"" + systemPrompt + "\\"},";',
            '  if (imageUrl != "") {',
            '    payload += "{\\"role\\":\\"user\\",\\"content\\":[";',
            '    payload += "{\\"type\\":\\"image_url\\",\\"image_url\\":{\\"url\\":\\"" + imageUrl + "\\"}},";',
            '    payload += "{\\"type\\":\\"text\\",\\"text\\":\\"" + inputText + "\\"}";',
            '    payload += "]}";',
            '  } else {',
            '    payload += "{\\"role\\":\\"user\\",\\"content\\":\\"" + inputText + "\\"}";',
            '  }',
            '  payload += "],";',
            '  payload += "\\"temperature\\":" + String(temperature);',
            '  payload += "}";',
            '  Serial.printf("发送URL图片请求，payload长度: %d\\n", payload.length());',
            '  return sendHttpRequestWithRetry(payload);',
            '}'
        ]
        
        Generator.addFunction("getGPTAnswer_urlimg", "String", "getGPTAnswer_urlimg", "String inputText, String imageUrl", func)
        Generator.addCode(`answer = "";`)
        Generator.addCode(`answer = getGPTAnswer_urlimg(${msg_urlimg}, ${url_img});`)
    }
    
    //% block="发送消息，文字[msg_camera]，摄像头照片" blockType="command"
    //% msg_camera.shadow="string" msg_camera.defl=图片里面讲了什么?
    export function myBlock7(parameter: any, block: any) {
        let msg_camera = parameter.msg_camera.code
        
        let func = [
            'String getGPTAnswer_camera(String inputText) {',
            '  if (inputText.length() == 0) {',
            '    Serial.println("错误：输入文本为空");',
            '    return ERROR_INVALID_INPUT;',
            '  }',
            '  K10_base64 k10base64;',
            '  String base64Image = k10base64.K10tobase64();',
            '  if (base64Image == "NULL" || base64Image.length() == 0) {',
            '    Serial.println("摄像头拍照失败");',
            '    return ERROR_CAMERA;',
            '  }',
            '  String payload = buildPayload(inputText, base64Image, "jpg");',
            '  Serial.printf("发送摄像头图片请求，payload长度: %d\\n", payload.length());',
            '  return sendHttpRequestWithRetry(payload);',
            '}'
        ]
        
        Generator.addFunction("getGPTAnswer_camera", "String", "getGPTAnswer_camera", "String inputText", func)
        Generator.addCode(`answer = "";`)
        Generator.addCode(`answer = getGPTAnswer_camera(${msg_camera});`)
    }
    
    //% block="获取结果" blockType="reporter"
    export function myBlock4(parameter: any, block: any) {
        Generator.addCode(`answer`)
    }

    //% block="获取返回的json[msg_json]参数[msg_key]值" blockType="reporter"
    //% msg_json.shadow="string" msg_json.defl={"猜拳":"石头"}
    //% msg_key.shadow="string" msg_key.defl=猜拳
    export function myBlock8(parameter: any, block: any) {
        let msg_json= parameter.msg_json.code
        let msg_key= parameter.msg_key.code

        let func = [
            'String getChoice(String msg_json , String msg_key) {',
            '   const char* jsonStr = msg_json.c_str();',
            '   ArduinoJson::DynamicJsonDocument doc(512);',
            '   ArduinoJson::DeserializationError error = ArduinoJson::deserializeJson(doc, jsonStr);',
            '   if (!error) {',
            '       if (doc.containsKey(msg_key)) {',
            '           String choice = doc[msg_key].as<String>();',
            '           return choice;',
            '       } else {',
            '           return "解析失败";',
            '       }',
            '   } else {',
            '       return "JSON语法错误";',
            '   }',
            '}'
        ]
        Generator.addInclude("ArduinoJsonK10", `#include <ArduinoJsonK10.h>`)
        Generator.addFunction("getChoice", "String", "getChoice", "String msg_json , String msg_key",func)
        Generator.addObject("myChoice", `String`, `myChoice;`)
        Generator.addCode(`getChoice(${msg_json},${msg_key})`)
        }

    // //% block="获取键值" blockType="reporter"
    // export function myBlock9(parameter: any, block: any) {
    //     Generator.addCode(`myChoice`)
    // }


} 