package com.izouma.nineth.web;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.github.kevinsawicki.http.HttpRequest;
import com.izouma.nineth.domain.BalanceRecord;
import com.izouma.nineth.domain.ExportWithdraw;
import com.izouma.nineth.domain.UserBalance;
import com.izouma.nineth.dto.PageQuery;
import com.izouma.nineth.enums.BalanceType;
import com.izouma.nineth.enums.PayMethod;
import com.izouma.nineth.exception.BusinessException;
import com.izouma.nineth.repo.AutoWithdrawRecordRepo;
import com.izouma.nineth.repo.BalanceRecordRepo;
import com.izouma.nineth.repo.ExportWithdrawRepo;
import com.izouma.nineth.repo.UserBalanceRepo;
import com.izouma.nineth.service.UserBalanceService;
import com.izouma.nineth.utils.DateTimeUtils;
import com.izouma.nineth.utils.JpaUtils;
import com.izouma.nineth.utils.SecurityUtils;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.IOUtils;
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.springframework.core.io.InputStreamResource;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.math.BigDecimal;
import java.time.Duration;
import java.time.LocalDate;
import java.util.concurrent.ExecutionException;

@RestController
@RequestMapping("/userBalance")
@AllArgsConstructor
@Slf4j
public class UserBalanceController extends BaseController {

    private final UserBalanceRepo               userBalanceRepo;
    private final BalanceRecordRepo             balanceRecordRepo;
    private final UserBalanceService            userBalanceService;
    private final ExportWithdrawRepo            exportWithdrawRepo;
    private final RedisTemplate<String, Object> redisTemplate;
    private final AutoWithdrawRecordRepo        autoWithdrawRecordRepo;

    @PostMapping("/all")
    @PreAuthorize("hasRole('ADMIN')")
    public Page<UserBalance> all(@RequestBody PageQuery pageQuery) {
        return userBalanceRepo.findAll(JpaUtils.toSpecification(pageQuery, UserBalance.class), JpaUtils.toPageRequest(pageQuery));
    }

    @PostMapping("/records")
    @PreAuthorize("hasRole('ADMIN')")
    public Page<BalanceRecord> records(@RequestBody PageQuery pageQuery) {
        return balanceRecordRepo.findAll(JpaUtils.toSpecification(pageQuery, BalanceRecord.class), JpaUtils.toPageRequest(pageQuery));
    }

    @PostMapping("/settle")
    @PreAuthorize("hasRole('ADMIN')")
    public void settle(@RequestParam LocalDate start, @RequestParam LocalDate end) {
        userBalanceService.settle(start, end);
    }

    @PostMapping(value = "/exportWithdraw")
    @PreAuthorize("hasRole('ADMIN')")
    public void exportWithdraw(String remark) throws IOException, InvalidFormatException {
        userBalanceService.exportWithdrawAsync(remark);
    }

    @PostMapping(value = "/exportHistory")
    @PreAuthorize("hasRole('ADMIN')")
    public Page<ExportWithdraw> exportHistory(Pageable pageable) {
        return exportWithdrawRepo.findAll(pageable);
    }

    @PostMapping("/importFail")
    @PreAuthorize("hasRole('ADMIN')")
    public void importFail(@RequestPart("withdrawList") MultipartFile withdrawFile,
                           @RequestPart("failList") MultipartFile failFile) throws IOException {
        userBalanceService.importFail(withdrawFile, failFile);
    }

    @PostMapping("/autoWithdraw")
    @PreAuthorize("hasRole('ADMIN')")
    public void autoWithdraw() throws ExecutionException, InterruptedException {

        LocalDate date = LocalDate.now();
        autoWithdrawRecordRepo.findByDate(date).ifPresent(a -> {
            throw new BusinessException("今日已经提现过");
        });

        userBalanceService.autoWithdraw(date);
    }

    @GetMapping("/my")
    public UserBalance my() {
        return userBalanceRepo.findById(SecurityUtils.getAuthenticatedUser().getId()).orElse(new UserBalance());
    }

    @GetMapping("/my/record")
    public Page<BalanceRecord> myRecord(Pageable pageable) {
        return balanceRecordRepo.findByUserId(SecurityUtils.getAuthenticatedUser().getId(), pageable);
    }

//    @PostMapping("/withdraw")
//    public void withdraw() {
//        userBalanceService.withdraw(SecurityUtils.getAuthenticatedUser().getId());
//    }

    @PostMapping(value = "/iap")
    public String iap(@RequestParam String receiptData) {
        String data = "{\"receipt-data\":\"" + receiptData + "\"}";
        String body = HttpRequest.post("https://buy.itunes.apple.com/verifyReceipt")
                .contentType("application/json")
                .send(data)
                .body();
        JSONObject jsonObject = JSON.parseObject(body);
        int status = jsonObject.getInteger("status");
        if (status == 21007) {
            jsonObject = JSON.parseObject(HttpRequest.post("https://sandbox.itunes.apple.com/verifyReceipt")
                    .contentType("application/json")
                    .send(data)
                    .body());
            status = jsonObject.getInteger("status");
        }
        log.info("verifyReceipt {}", JSON.toJSONString(jsonObject, true));
        if (status == 0) {
            JSONObject inApp = jsonObject.getJSONObject("receipt").getJSONArray("in_app").getJSONObject(0);
            BigDecimal amount = inApp.getBigDecimal("product_id");
            userBalanceService.modifyBalance(SecurityUtils.getAuthenticatedUser().getId(), amount, BalanceType.RECHARGE,
                    null, false, null);
        }
        return "ok";
    }
}
