package com.lion.lionwebsite.Service;

import com.lion.lionwebsite.Domain.GalleryForQuery;
import com.lion.lionwebsite.Util.Response;
import com.fasterxml.jackson.databind.ObjectMapper;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import org.springframework.stereotype.Service;

import java.io.*;
import java.util.*;

@Service
@Slf4j
public class QueryService {

    String CachePath = "/storage/hentaiCache/";

    public String query(String keyword, String prev, String next) {
        Response response = Response.generateResponse();
        String get;
        String param = "?f_search=" + keyword.replace(" ", "+");

        if(prev != null)
            param += "&prev=" + prev;
        else if(next != null)
            param += "&next=" + next;

        try{
            get = requests("https://exhentai.org/" + param, false, null, null);
        }catch (IOException e){
            e.printStackTrace();
            response.failure("query failure");
            return response.toJSONString();
        }

        Document parse = Jsoup.parse(get);
        Elements elements = parse.select("body > div.ido > div:nth-child(2) > table > tbody > tr");


        ArrayList<GalleryForQuery> galleries = new ArrayList<>();
        ListIterator<Element> elementListIterator = elements.listIterator();
        try {
            elementListIterator.next();                                             //skip firstlink
        }catch (NullPointerException | NoSuchElementException e){
            response.failure("没有搜索到结果");
            return response.toJSONString();
        }

        while (elementListIterator.hasNext()){
            Element element = elementListIterator.next();
            GalleryForQuery gallery = new GalleryForQuery();
            gallery.setType(element.child(0).text());                                                      //type
            String src = element.child(1).select("img").attr("src");
            if (src.startsWith("data"))
                src = element.child(1).select("img").attr("data-src");
            src = src.replace("https://s.exhentai.org", "");
            gallery.setThumbnailUrl(src);                                 //thumbnailSrc
            gallery.setUploadTime(element.child(1).select("div > div [onclick]").get(1).text());          //uploadTime
            gallery.setLink(element.child(2).child(0).attr("href"));                         //link
            gallery.setName(element.child(2).child(0).child(0).text());                           //name
            gallery.setPage(Integer.parseInt(element.child(3).child(1).text().split(" ")[0]));   //page

            galleries.add(gallery);
        }


        response.success(new ObjectMapper().valueToTree(galleries).toString());
        Elements nextLink = parse.select("#unext");
        if(nextLink.hasAttr("href"))
            response.set("next", nextLink.attr("href"));

        Elements previousLink = parse.select("#uprev");
        if(previousLink.hasAttr("href"))
            response.set("previous", previousLink.attr("href"));

        Elements firstLink = parse.select("#ufirst");
        if(firstLink.hasAttr("href"))
            response.set("first", firstLink.attr("href"));

        Elements lastLink = parse.select("#ulast");
        if(lastLink.hasAttr("href"))
            response.set("last", lastLink.attr("href"));

        return response.toJSONString();
    }

    public void image(HttpServletResponse response, String path){
        String imageName = path.substring(path.lastIndexOf("/") + 1);
        File image = new File(CachePath, imageName);
        if(image.isFile()){             //hit cache
            log.info("hit cache:{}", imageName);
            try (BufferedInputStream bufferedInputStream = new BufferedInputStream(new FileInputStream(image));
                BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(response.getOutputStream())){
                bufferedInputStream.transferTo(bufferedOutputStream);
            }catch (IOException e){
                e.printStackTrace();
            }
        }
        else{                          // transfer image and save it as cache
            log.info("miss cache:{}", imageName);
            try {
                if(!path.startsWith("/t"))
                    path = "/t" + path;
                requests("https://s.exhentai.org" + path, true, response, new FileOutputStream(image));
            }catch (IOException e){
                e.printStackTrace();
            }
        }
    }

    public String requests(String url, boolean isDirect, HttpServletResponse response, OutputStream local) throws IOException {
        CloseableHttpClient httpClient = HttpClients.createDefault();
        CloseableHttpResponse httpResponse;

        HashMap<String, String> headers = new HashMap<>();
        headers.put("User-Agent", "Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.82 Safari/537.36");
        headers.put("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8");
        headers.put("Upgrade-Insecure-Requests", "1");
        headers.put("Cookie", "ipb_member_id=5774855; ipb_pass_hash=4b061c3abe25289568b5a8e0123fb3b9; igneous=cea2e08fb; sk=oye107wk02gtomb56x65dmv4qzbn; nw=1");

        HttpGet httpGet = new HttpGet(url);
        for (Map.Entry<String, String> header: headers.entrySet()){
            httpGet.addHeader(header.getKey(), header.getValue());
        }

        httpResponse = httpClient.execute(httpGet);

        HttpEntity responseEntity = httpResponse.getEntity();
        int statusCode = httpResponse.getStatusLine().getStatusCode();

        try {
            if (statusCode == 200) {
                if (isDirect) {
                    InputStream inputStream = new BufferedInputStream(responseEntity.getContent());
                    byte[] bytes = inputStream.readAllBytes();
                    if(response != null) {
                        OutputStream outputStream = response.getOutputStream();
                        outputStream.write(bytes);
                        outputStream.close();
                    }
                    if(local != null){
                        local.write(bytes);
                        local.close();
                    }
                    inputStream.close();
                    return null;
                } else {
                    StringBuilder stringBuilder = new StringBuilder();
                    String str;
                    BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(responseEntity.getContent()));
                    while ((str = bufferedReader.readLine()) != null) {
                        stringBuilder.append(str).append("\n");
                    }
                    return stringBuilder.toString();
                }
            } else {
                System.out.println(statusCode);
                return null;
            }
        }finally {
            httpClient.close();
            httpResponse.close();
        }

    }
}
