package v1

import (
	"bytes"
	"context"
	"encoding/json"

	"github.com/pingcap-inc/pchub/pkg/log"
)

type record struct {
	RecordID string `json:"record_id"`
}

func FreshBiTable(ctx context.Context, appToken, tableID string, records interface{}, tok string) error {
	biRecords, err := GetBiRecords(ctx, appToken, tableID, tok)
	if err != nil {
		return err
	}

	delIDs := make([]string, 0)
	for _, biRecord := range biRecords {
		if biRecord == nil {
			continue
		}
		var rds []record
		err = json.Unmarshal(biRecord, &rds)
		if err != nil {
			log.L(ctx).Errorf("unmarshal bi record failed: %s", err.Error())

			return err
		}

		for _, re := range rds {
			delIDs = append(delIDs, re.RecordID)
		}
	}

	if len(delIDs) > 0 {
		err = DelBiRecords(ctx, appToken, tableID, delIDs, tok)
		if err != nil {
			return err
		}
	}

	err = AddBiRecords(ctx, appToken, tableID, records, tok)
	if err != nil {
		return err
	}

	log.L(ctx).Infof("fresh bi table success: %s", tableID)

	return nil
}

func AddBiRecords(ctx context.Context, appToken, tableID string, records interface{}, tok string) error {
	url := "/bitable/v1/apps/" + appToken + "/tables/" + tableID + "/records/batch_create"

	body := map[string]interface{}{
		"records": records,
	}

	marshalBody, _ := json.Marshal(body)
	_, err := comSrv.GetDataByReqLarkAPI(ctx, "POST", LarkOpenAPIBase+url, bytes.NewReader(marshalBody), nil, tok)
	if err != nil {
		return err
	}

	log.L(ctx).Infof("add bi records success: %s", tableID)

	return nil
}

func DelBiRecords(ctx context.Context, appToken, tableID string, recordIDs []string, tok string) error {
	url := "/bitable/v1/apps/" + appToken + "/tables/" + tableID + "/records/batch_delete"
	body := map[string]interface{}{
		"records": recordIDs,
	}

	marshalBody, _ := json.Marshal(body)
	_, err := comSrv.GetDataByReqLarkAPI(ctx, "POST", LarkOpenAPIBase+url, bytes.NewReader(marshalBody), nil, tok)
	if err != nil {
		return err
	}

	log.L(ctx).Infof("del bi records success: %s", tableID)

	return nil
}

func GetBiRecords(ctx context.Context, appToken, tableID string, tok string) ([]json.RawMessage, error) {
	url := "/bitable/v1/apps/" + appToken + "/tables/" + tableID + "/records"
	params := map[string]string{
		"page_size":  "500",
		"page_token": "",
	}

	items := make([]json.RawMessage, 0)

	for {
		resp, err := comSrv.GetDataByReqLarkAPI(ctx, "GET", LarkOpenAPIBase+url, nil, nil, tok)
		if err != nil {
			return nil, err
		}

		var comResp respData
		err = json.Unmarshal(resp, &comResp)

		if err != nil {
			log.L(ctx).Errorf("unmarshal resp failed: %s", err.Error())

			return nil, err
		}

		items = append(items, comResp.Items)

		if comResp.HasMore {
			params["page_token"] = comResp.PageToken
		} else {
			break
		}
	}
	log.L(ctx).Infof("get bi records success: %s", tableID)

	return items, nil
}
