package com.ecep.contract;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.net.CookieStore;
import java.net.HttpCookie;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;

public class MyPersistentCookieStore implements CookieStore {


    private final File file;
    private final ObjectMapper objectMapper;
    private Map<URI, List<HttpCookie>> cookiesMap = new HashMap<>();

    public MyPersistentCookieStore(File file, ObjectMapper objectMapper) {
        this.file = file;
        this.objectMapper = objectMapper;
        if (file != null && file.exists()) {
            loadFromFile2();
        }
    }

    private void loadFromFile2() {
        try {
            ObjectNode root = (ObjectNode) objectMapper.readTree(file);
            for (Iterator<Map.Entry<String, JsonNode>> it = root.fields(); it.hasNext(); ) {
                Map.Entry<String, JsonNode> entry = it.next();
                String key = entry.getKey();
                ArrayNode value = (ArrayNode) entry.getValue();

                List<HttpCookie> cookies = new ArrayList<>();
                for (JsonNode node1 : value) {
                    HttpCookie cookie = new HttpCookie(node1.get("name").asText(), node1.get("value").asText());
                    objectMapper.updateValue(node1, cookie);
                    cookies.add(cookie);
                }
                URI uri = URI.create(key);
                System.out.println(key + " -> " + uri);
                cookiesMap.put(uri, cookies);
            }

        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    public void saveToFile2() {
        try {
            objectMapper.writeValue(file, cookiesMap);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    public void loadFromFile(File file) {
        try (BufferedReader reader = new BufferedReader(new FileReader(file))) {
            String line;
            while ((line = reader.readLine()) != null) {
                // 假设格式为: name=value;domain=domain;path=path;expires=expires;
                String[] parts = line.split(";");
                String nameValue = parts[0];
                String[] nameValueParts = nameValue.split("=");
                String name = nameValueParts[0];
                String value = nameValueParts.length > 1 ? nameValueParts[1] : "";
                HttpCookie cookie = new HttpCookie(name, value);
                for (int i = 1; i < parts.length; i++) {
                    String[] attribute = parts[i].split("=");
                    if (attribute[0].equals("domain")) {
                        cookie.setDomain(attribute[1]);
                    } else if (attribute[0].equals("path")) {
                        cookie.setPath(attribute[1]);
                    } else if (attribute[0].equals("expires")) {
                        // 解析日期格式并设置过期时间
                        // 这里只是示例，实际需要正确解析日期格式
                        Date expiresDate = new Date(Long.parseLong(attribute[1]));
                        cookie.setMaxAge(expiresDate.getTime() - System.currentTimeMillis());
                    }
                }
                URI uri = URI.create(cookie.getDomain());
                List<HttpCookie> cookies = cookiesMap.getOrDefault(uri, new ArrayList<>());
                cookies.add(cookie);
                cookiesMap.put(uri, cookies);
            }
        } catch (IOException e) {
            // 处理文件读取错误
            e.printStackTrace();
        }
    }

    public void saveToFile() {
        try (BufferedWriter writer = new BufferedWriter(new FileWriter(file))) {
            for (Map.Entry<URI, List<HttpCookie>> entry : cookiesMap.entrySet()) {
                for (HttpCookie cookie : entry.getValue()) {
                    String line = cookie.getName() + "=" + cookie.getValue() + ";domain=" + cookie.getDomain() + ";path=" + cookie.getPath();
                    if (cookie.getMaxAge() > 0) {
                        line += ";expires=" + (System.currentTimeMillis() + cookie.getMaxAge());
                    }
                    writer.write(line);
                    writer.newLine();
                }
            }
        } catch (IOException e) {
            // 处理文件写入错误
            e.printStackTrace();
        }
    }

    @Override
    public void add(URI uri, HttpCookie cookie) {
        if (cookie == null) {
            throw new NullPointerException("cookie is null");
        }

        if (cookie.getDomain() != null) {
            URI key = getEffectiveURI(cookie);
            List<HttpCookie> cookies = cookiesMap.getOrDefault(key, new ArrayList<>());
            cookies.remove(cookie);
            cookies.add(cookie);
            cookiesMap.put(key, cookies);
        }

        if (uri != null) {
            URI key = getEffectiveURI(uri);
            List<HttpCookie> cookies = cookiesMap.getOrDefault(key, new ArrayList<>());
            cookies.remove(cookie);
            cookies.add(cookie);
            cookiesMap.put(key, cookies);
        }
        saveToFile2();
    }

    @Override
    public List<HttpCookie> get(URI uri) {
        URI effectiveURI = getEffectiveURI(uri);
        System.out.println("effectiveURI = " + effectiveURI);
        return cookiesMap.getOrDefault(effectiveURI, new ArrayList<>());
    }

    @Override
    public List<HttpCookie> getCookies() {
        return cookiesMap.values().stream().flatMap(List::stream).toList();
    }

    @Override
    public List<URI> getURIs() {
        return cookiesMap.keySet().stream().toList();
    }

    @Override
    public boolean remove(URI uri, HttpCookie cookie) {
        URI key = getEffectiveURI(uri);
        List<HttpCookie> httpCookies = cookiesMap.get(key);
        if (httpCookies == null) {
            return false;
        }
        return httpCookies.remove(cookie);
    }

    @Override
    public boolean removeAll() {
        cookiesMap.clear();
        return true;
    }

    private URI getEffectiveURI(URI uri) {
        URI effectiveURI = null;
        try {
            effectiveURI = new URI("http",
                    uri.getHost(),
                    null,  // path component
                    null,  // query component
                    null   // fragment component
            );
        } catch (URISyntaxException ignored) {
            ignored.printStackTrace();
            effectiveURI = uri;
        }

        return effectiveURI;
    }

    private URI getEffectiveURI(HttpCookie cookie) {
        URI effectiveURI = null;
        try {
            effectiveURI = new URI("http",
                    cookie.getDomain(),
                    null,  // path component
                    null,  // query component
                    null   // fragment component
            );
        } catch (URISyntaxException ignored) {

        }

        return effectiveURI;
    }
}
