package cn.edu.ecnu.stu.bookstore;

import cn.edu.ecnu.stu.bookstore.component.Constants;
import cn.edu.ecnu.stu.bookstore.component.Result;
import cn.edu.ecnu.stu.bookstore.mapper.OrderMapper;
import cn.edu.ecnu.stu.bookstore.pojo.Order;
import cn.edu.ecnu.stu.bookstore.pojo.OrderStatus;
import cn.edu.ecnu.stu.bookstore.pojo.User;
import cn.edu.ecnu.stu.bookstore.utils.ImageUtil;
import cn.edu.ecnu.stu.bookstore.util.RequestUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

import java.math.BigDecimal;
import java.util.*;

@SpringBootTest
public class BuyerTest {

    private String token;

    private final String storeId = "store" + UUID.randomUUID();

    private List<String> bookIds;

    private Integer userId;

    private String username;

    private String password;

    @Autowired
    private OrderMapper orderMapper;

    public void init() {
        if(username != null)
            return;
        String url = Constants.URL_PREFIX + "/auth/register";
        Map<String, Object> map = new HashMap<>();
        username = UUID.randomUUID().toString();
        password = username + "x";
        map.put("username", username);
        map.put("password", password);
        Result result = RequestUtil.post(url, map, null);
        assert result != null && result.getCode() != null && result.getCode().equals(Constants.SUCCESS);

        url = Constants.URL_PREFIX + "/auth/login";
        result = RequestUtil.post(url, map, null);
        assert result != null && result.getCode() != null && result.getCode().equals(Constants.SUCCESS);

        JSONObject data = (JSONObject) result.getData();
        token = data.getString("token");
        userId = data.getObject("user", User.class).getId();

        url = Constants.URL_PREFIX + "/seller/create_store";
        map = new HashMap<>();
        map.put("storeId", storeId);
        result = RequestUtil.post(url, map, token);
        assert result != null && Constants.SUCCESS.equals(result.getCode());

        result = RequestUtil.post(url, map, token);
        assert result != null && Constants.CLIENT_ERROR.equals(result.getCode());

        url = Constants.URL_PREFIX + "/seller/add_book";
        String bookId = UUID.randomUUID().toString();
        String title = "title" + UUID.randomUUID();
        String author = "author" + UUID.randomUUID();
        String publisher = "publisher" + UUID.randomUUID();
        BigDecimal price = new BigDecimal("29.88");
        String authorIntro = "authorIntro" + UUID.randomUUID();
        String bookIntro = "bookIntro" + UUID.randomUUID();
        String content = "content" + UUID.randomUUID();
        List<String> tags = Arrays.asList("tag" + UUID.randomUUID(), "tag" + UUID.randomUUID());
        List<String> pictures = Arrays.asList(ImageUtil.convertImageToBase64Str("ff3c65cd-497e-4b17-aa55-5882a38ed2fd.png"));
        map = new HashMap<>();
        map.put("storeId", storeId);
        map.put("bookId", bookId);
        map.put("title", title);
        map.put("author", author);
        map.put("publisher", publisher);
        map.put("price", price);
        map.put("authorIntro", authorIntro);
        map.put("bookIntro", bookIntro);
        map.put("content", content);
        map.put("tags", tags);
        map.put("pictures", pictures);
        result = RequestUtil.post(url, map, token);
        assert result != null && Constants.SUCCESS.equals(result.getCode());

        map.put("bookId", bookId + "x");
        bookIds = Arrays.asList(bookId, bookId + "x");
        result = RequestUtil.post(url, map, token);
        assert result != null && Constants.SUCCESS.equals(result.getCode());

        url = Constants.URL_PREFIX + "/seller/add_stock_level";
        map = new HashMap<>();
        map.put("storeId", storeId);
        map.put("addStockLevel", 100);
        for (String id : bookIds) {
            map.put("bookId", id);
            result = RequestUtil.post(url, map, token);
            assert result != null && Constants.SUCCESS.equals(result.getCode());
        }
    }

    @Test
    public void testNewOrder() {
        init();
        String url = Constants.URL_PREFIX + "/buyer/new_order";
        HashMap<String, Object> map = new HashMap<>();
        map.put("storeId", storeId);
        List<Map<String, Object>> list = new LinkedList<>();
        int c = 1;
        for (String bookId : bookIds) {
            HashMap<String, Object> map0 = new HashMap<>();
            map0.put("id", bookId);
            map0.put("count", c++);
            list.add(map0);
        }
        map.put("books", list);
        Result result = RequestUtil.post(url, map, token);
        assert result != null && Constants.SUCCESS.equals(result.getCode());

        list.get(0).put("id", "我爱数据库");
        result = RequestUtil.post(url, map, token);
        assert result != null && Constants.CLIENT_ERROR.equals(result.getCode());
    }

    @Test
    public void testAddFunds() {
        init();
        String url = Constants.URL_PREFIX + "/buyer/add_funds";
        HashMap<String, Object> map = new HashMap<>();
        map.put("username", username);
        map.put("password", password);
        map.put("addValue", 1000);
        Result result = RequestUtil.post(url, map, null);
        assert result != null && Constants.SUCCESS.equals(result.getCode());
    }

    @Test
    public void testPayment() {
        init();
        testNewOrder();
        testAddFunds();

        String url = Constants.URL_PREFIX + "/buyer/order";
        Result result = RequestUtil.get(url, null, token);
        JSONArray data = (JSONArray) result.getData();
        Object[] objects = data.stream().toArray();
        url = Constants.URL_PREFIX + "/buyer/payment";
        HashMap<String, Object> map = new HashMap<>();
        map.put("userId", userId);
        map.put("password", password);
        for (Object obj : objects) {
            JSONObject obj1 = (JSONObject) obj;
            map.put("orderId", obj1.getString("orderId"));
            result = RequestUtil.post(url, map, null);
            assert result != null && Constants.SUCCESS.equals(result.getCode());
        }
    }

    @Test
    public void testTakeDelivery() {
        testNewOrder();
        String orderId = UUID.randomUUID().toString();

        Order order = new Order(orderId, userId, null, null, new BigDecimal("123.23"), OrderStatus.WAIT_RECEIVE, storeId, null);
        String body = JSON.toJSONString(order);
        String url = Constants.URL_PREFIX + "/order/add";
        Result result = RequestUtil.post(url, body, token);
        assert result != null && Constants.SUCCESS.equals(result.getCode());
        url = Constants.URL_PREFIX + "/buyer/take_delivery";
        HashMap<String, Object> map = new HashMap<>();
        map.put("orderId", orderId);
        result = RequestUtil.post(url, map, token);
        assert result != null && Constants.SUCCESS.equals(result.getCode());

    }
}
