package org.jeecg.modules.okki.translate.service;

import com.amazonaws.ClientConfiguration;
import com.amazonaws.DefaultRequest;
import com.amazonaws.Request;
import com.amazonaws.Response;
import com.amazonaws.auth.AWS4Signer;
import com.amazonaws.auth.DefaultAWSCredentialsProviderChain;
import com.amazonaws.http.AmazonHttpClient;
import com.amazonaws.http.ExecutionContext;
import com.amazonaws.http.HttpMethodName;
import com.google.gson.Gson;
import lombok.extern.slf4j.Slf4j;
import org.jeecg.modules.okki.translate.dto.TranslateRequestDto;
import org.jeecg.modules.okki.translate.dto.TranslateResults;
import org.jeecg.modules.okki.translate.param.AwsTranslateOptionParam;
import org.jeecg.modules.okki.translate.param.AwsTranslateParam;
import org.jeecg.modules.okki.translate.tools.ErrorHandler;
import org.jeecg.modules.okki.translate.tools.ResponseHandler;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.util.*;
import java.util.concurrent.*;

@Slf4j
@Service
public class AwsTranslateService {

    @Value("${aws.region}")
    private String Region;

    @Value("${aws.host}")
    private String Host;

    @Value("${aws.service}")
    private String Service;

    public static final Map<String, String> LANGUAGE_MAP;

    private final ExecutorService executorService = Executors.newFixedThreadPool(10);

    public TranslateResults doTranslate(TranslateRequestDto translateRequestDto) throws UnsupportedEncodingException {
        // 将OK语言码转换为百度语言代码
        translateRequestDto.setToBaiduCode(new ArrayList<>());
        translateRequestDto.setFremBaiduCode(LANGUAGE_MAP.get(translateRequestDto.getFrom()));
        for (int i = 0; i < translateRequestDto.getTo().size(); i++) {
            translateRequestDto.getToBaiduCode().add(LANGUAGE_MAP.get(translateRequestDto.getTo().get(i)));
        }

        String fromLanguage = translateRequestDto.getFrom();
        List<String> targetLanguages = translateRequestDto.getTo();
        Map<String, String> contents = translateRequestDto.getContents();

        TranslateResults results = new TranslateResults();
        Map<String, Map<String, String>> translatedInfo = new ConcurrentHashMap<>();

        List<Future<Void>> futures = new ArrayList<>();

        // 预解码所有内容
        Map<String, String> decodedContents = new HashMap<>();
        for (Map.Entry<String, String> entry : contents.entrySet()) {
            decodedContents.put(entry.getKey(), new String(Base64.getDecoder().decode(entry.getValue())));
        }

        for (String targetLanguage : targetLanguages) {
            for (Map.Entry<String, String> entry : decodedContents.entrySet()) {
                futures.add(executorService.submit(() -> {
                    processTranslation(entry.getKey(), entry.getValue(), fromLanguage, targetLanguage, LANGUAGE_MAP.get(fromLanguage), LANGUAGE_MAP.get(targetLanguage), translatedInfo, contents.get(entry.getKey()));
                    return null;
                }));
            }
        }

        // 等待所有任务完成
        for (Future<Void> future : futures) {
            try {
                future.get();
            } catch (InterruptedException | ExecutionException e) {
                log.error("翻译任务执行出错", e);
                Thread.currentThread().interrupt();  // 处理中断
            }
        }

        results.setMsg("successful");
        results.setData(translatedInfo);

        return results;
    }

    private void processTranslation(String key, String decodedSrc, String fromLanguage, String targetLanguage , String fromLanguageTransCode,  String targetLanguageTransCode, Map<String, Map<String, String>> translatedInfo, String originalValue) {
        try {
            String transObj = doSingleTranslate(decodedSrc, fromLanguageTransCode, targetLanguageTransCode);
            String encodedDst = Base64.getEncoder().encodeToString(transObj.getBytes());
            Map<String, String> trans = translatedInfo.computeIfAbsent(key, k -> new HashMap<>());
            trans.put(targetLanguage, encodedDst);
            trans.put("_original", originalValue);

        } catch (Exception e) {
            log.error("处理翻译时发生异常", e);
        }
    }

    private String doSingleTranslate(String contents, String fromLanguage, String targetLanguage) {
        final AwsTranslateParam awsTranslateParam = new AwsTranslateParam();
        final AwsTranslateOptionParam awsTranslateOptionParam = new AwsTranslateOptionParam();
        awsTranslateOptionParam.setSourceLanguage(fromLanguage);
        awsTranslateOptionParam.setTargetLanguage(targetLanguage);
        awsTranslateOptionParam.setModel("CLAUDE_3_HAIKU");
        awsTranslateOptionParam.setMode("TEXT");
        awsTranslateParam.setOption(awsTranslateOptionParam);
        awsTranslateParam.setText(contents);
        Gson gson = new Gson();
        String str = gson.toJson(awsTranslateParam);
        InputStream is = new ByteArrayInputStream(str.getBytes());
        Map<String, String> headerMap = new HashMap<>();
        headerMap.put("content-type", "application/json");
        Request<Void> request = new DefaultRequest<>(Service); //Request to Lambda
        request.setHttpMethod(HttpMethodName.POST);
        request.setContent(is);
        request.setHeaders(headerMap);
        request.setEndpoint(URI.create(Host + "/api/v1/generation/translate"));
        //Sign it...
        AWS4Signer signer = new AWS4Signer();
        signer.setRegionName(Region);
        signer.setServiceName(request.getServiceName());
        // automatically get the credentials from Env for EC2/Lambda roles
        signer.sign(request, new DefaultAWSCredentialsProviderChain().getCredentials());
        //Execute it and get the response...
        Response<String> rsp = new AmazonHttpClient(new ClientConfiguration())
                .requestExecutionBuilder()
                .executionContext(new ExecutionContext(true))
                .request(request)
                .errorResponseHandler(new ErrorHandler())
                .execute(new ResponseHandler());
        return rsp.getAwsResponse();
    }

    static {
        LANGUAGE_MAP = new HashMap<>();
        LANGUAGE_MAP.put("zh", "ZH_CN");
        LANGUAGE_MAP.put("en", "EN_US");
        LANGUAGE_MAP.put("ar", "AR");
        LANGUAGE_MAP.put("bg", "BG");
        LANGUAGE_MAP.put("hr", "HR");
        LANGUAGE_MAP.put("cs", "CS");
        LANGUAGE_MAP.put("da", "DA");
        LANGUAGE_MAP.put("nl", "NL");
        LANGUAGE_MAP.put("fi", "FI");
        LANGUAGE_MAP.put("fr", "FR");
        LANGUAGE_MAP.put("de", "DE");
        LANGUAGE_MAP.put("el", "EL");
        LANGUAGE_MAP.put("hi", "HI");
        LANGUAGE_MAP.put("it", "IT");
        LANGUAGE_MAP.put("ja", "JA");
        LANGUAGE_MAP.put("ko", "KO");
        LANGUAGE_MAP.put("no", "NB");
        LANGUAGE_MAP.put("pl", "PL");
        LANGUAGE_MAP.put("pt", "PT");
        LANGUAGE_MAP.put("ro", "RO");
        LANGUAGE_MAP.put("ru", "RU");
        LANGUAGE_MAP.put("es", "ES");
        LANGUAGE_MAP.put("sv", "SV");
        LANGUAGE_MAP.put("ca", "CA");
        LANGUAGE_MAP.put("tl", "FIL");
        LANGUAGE_MAP.put("iw", "HE");
        LANGUAGE_MAP.put("id", "ID");
        LANGUAGE_MAP.put("lv", "LV");
        LANGUAGE_MAP.put("lt", "LT");
        LANGUAGE_MAP.put("sr", "SR");
        LANGUAGE_MAP.put("sk", "SK");
        LANGUAGE_MAP.put("sl", "SL");
        LANGUAGE_MAP.put("uk", "UK");
        LANGUAGE_MAP.put("vi", "VI");
        LANGUAGE_MAP.put("gl", "GL");
        LANGUAGE_MAP.put("hu", "HU");
        LANGUAGE_MAP.put("mt", "MT");
        LANGUAGE_MAP.put("th", "TH");
        LANGUAGE_MAP.put("tr", "TR");
        LANGUAGE_MAP.put("fa", "FA");
        LANGUAGE_MAP.put("af", "AF");
        LANGUAGE_MAP.put("ms", "MS");
        LANGUAGE_MAP.put("sw", "SW");
        LANGUAGE_MAP.put("ga", "GA");
        LANGUAGE_MAP.put("cy", "CY");
        LANGUAGE_MAP.put("is", "IS");
        LANGUAGE_MAP.put("mk", "MK");
        LANGUAGE_MAP.put("sq", "SQ");
        LANGUAGE_MAP.put("et", "ET");
    }

//    enum Language {
//        @documentation("Chinese")
//        ZH_CN
//        @documentation("English")
//        EN_US
//        @documentation("Arabic")
//                AR
//        @documentation("Bulgarian")
//        BG
//        @documentation("Croatian")
//                HR
//        @documentation("Czech")
//        CS
//        @documentation("Danish")
//                DA
//        @documentation("Dutch")
//        NL
//        @documentation("Finnish")
//                FI
//        @documentation("French")
//        FR
//        @documentation("German")
//                DE
//        @documentation("Greek")
//        EL
//        @documentation("Hindi")
//                HI
//        @documentation("Italian")
//        IT
//        @documentation("Japanese")
//                JA
//        @documentation("Korean")
//        KO
//        @documentation("Norwegian")
//                NB
//        @documentation("Polish")
//        PL
//        @documentation("Portuguese")
//                PT
//        @documentation("Romanian")
//        RO
//        @documentation("Russian")
//                RU
//        @documentation("Spanish")
//        ES
//        @documentation("Swedish")
//                SV
//        @documentation("Catalan")
//        CA
//        @documentation("Filipino")
//                FIL
//        @documentation("Hebrew")
//        HE
//        @documentation("Indonesian")
//                ID
//        @documentation("Latvian")
//        LV
//        @documentation("Lithuanian")
//                LT
//        @documentation("Serbian")
//        SR
//        @documentation("Slovak")
//                SK
//        @documentation("Slovenian")
//        SL
//        @documentation("Ukrainian")
//                UK
//        @documentation("Vietnamese")
//        VI
//        @documentation("Galician")
//                GL
//        @documentation("Hungarian")
//        HU
//        @documentation("Maltese")
//                MT
//        @documentation("Thai")
//        TH
//        @documentation("Turkish")
//                TR
//        @documentation("Persian")
//        FA
//        @documentation("Afrikaans")
//                AF
//        @documentation("Malay")
//        MS
//        @documentation("Swahili")
//                SW
//        @documentation("Irish")
//        GA
//        @documentation("Welsh")
//                CY
//        @documentation("Icelandic")
//        IS
//        @documentation("Macedonian")
//                MK
//        @documentation("Albanian")
//        SQ
//        @documentation("Estonian")
//                ET
//        }
}
