package newbond

import (
	"database/sql"
	"encoding/json"
	"fmt"
	"io"
	"log"
	"net/http"
	"time"

	"git.lxtend.com/lixiangwuxian/qqbot/action"
	"git.lxtend.com/lixiangwuxian/qqbot/model"
	"git.lxtend.com/lixiangwuxian/qqbot/sqlite3"
	"git.lxtend.com/lixiangwuxian/qqbot/util"
)

func init() {
	createNewBondListenGroupTableSQL := `
	CREATE TABLE IF NOT EXISTS new_bond_listen_group (
		group_id INT PRIMARY KEY
	);
	`
	createNewBondInfoTableSQL := `CREATE TABLE BondData (
		SecurityCode VARCHAR(10) NOT NULL,
		SecuCode VARCHAR(15) NOT NULL,
		TradeMarket VARCHAR(10) NOT NULL,
		SecurityNameAbbr VARCHAR(50) NOT NULL,
		PRIMARY KEY (SecurityCode)
	);
	`
	sqlite3.TryCreateTable(createNewBondListenGroupTableSQL)
	sqlite3.TryCreateTable(createNewBondInfoTableSQL)
	go RoundCheckNewBond()
}

func GetBondsData() ([]BondData, error) {
	url := "https://datacenter-web.eastmoney.com/api/data/v1/get?sortColumns=PUBLIC_START_DATE%2CSECURITY_CODE&sortTypes=-1%2C-1&pageSize=50&pageNumber=1&reportName=RPT_BOND_CB_LIST&columns=ALL&quoteColumns=f2~01~CONVERT_STOCK_CODE~CONVERT_STOCK_PRICE%2Cf235~10~SECURITY_CODE~TRANSFER_PRICE%2Cf236~10~SECURITY_CODE~TRANSFER_VALUE%2Cf2~10~SECURITY_CODE~CURRENT_BOND_PRICE%2Cf237~10~SECURITY_CODE~TRANSFER_PREMIUM_RATIO%2Cf239~10~SECURITY_CODE~RESALE_TRIG_PRICE%2Cf240~10~SECURITY_CODE~REDEEM_TRIG_PRICE%2Cf23~01~CONVERT_STOCK_CODE~PBV_RATIO&quoteType=0&source=WEB&client=WEB"

	resp, err := http.Get(url)
	if err != nil {
		return nil, err
	}
	defer resp.Body.Close()

	if resp.StatusCode != http.StatusOK {
		return nil, fmt.Errorf("status code %d", resp.StatusCode)
	}

	body, err := io.ReadAll(resp.Body)
	if err != nil {
		return nil, err
	}

	var apiResponse BondResponse
	err = json.Unmarshal(body, &apiResponse)
	if err != nil {
		return nil, err
	}

	return apiResponse.Result.Data, nil
}

func AddGroupListen(groupID int) error {
	tx, err := sqlite3.GetTran()
	if err != nil {
		return err
	}
	defer tx.Rollback()
	tx.Exec("INSERT INTO new_bond_listen_group (group_id) VALUES (?)", groupID)
	if err := tx.Commit(); err != nil {
		return err
	}
	return nil
}

func RemoveGroupListen(groupID int) error {
	tx, err := sqlite3.GetTran()
	if err != nil {
		return err
	}
	defer tx.Rollback()
	tx.Exec("DELETE FROM new_bond_listen_group WHERE group_id = ?", groupID)
	if err := tx.Commit(); err != nil {
		return err
	}
	return nil
}

func BondDataExists(securityCode string) (bool, error) {
	db := sqlite3.GetDB()
	var count int
	if err := db.Get(&count, "SELECT COUNT(*) FROM BondData WHERE SecurityCode = ?", securityCode); err != nil {
		return false, err
	}
	return count > 0, nil
}

func AddBondData(data BondData) error {
	tx, err := sqlite3.GetTran()
	if err != nil {
		return err
	}
	defer tx.Rollback()
	query := `INSERT INTO BondData (
		SecurityCode, SecuCode, TradeMarket, SecurityNameAbbr
	) VALUES (
		:SecurityCode, :SecuCode, :TradeMarket, :SecurityNameAbbr
	)`

	_, err = tx.NamedExec(query, data)
	if err != nil {
		return err
	}
	if err := tx.Commit(); err != nil {
		return err
	}
	return nil
}

func GetGroupListens() ([]int, error) {
	db := sqlite3.GetDB()
	var groupIDs []int
	if err := db.Select(&groupIDs, "SELECT group_id FROM new_bond_listen_group"); err != nil && err != sql.ErrNoRows {
		return nil, err
	}
	return groupIDs, nil
}

func RoundCheckNewBond() {
	time.Sleep(5 * time.Minute)
	for !action.ActionManager.Started() {
		time.Sleep(5 * time.Minute)
	}
	// once := true
	util.AddCycleTask("checkNewBond", 5*time.Minute, 5*time.Minute, func() {
		bonds, err := GetBondsData()
		if bonds == nil || err != nil {
			log.Printf("Error getting bonds data: %v\n", err)
			return
		}
		groups, err := GetGroupListens()
		if err != nil {
			log.Printf("Error getting group listens: %v\n", err)
			return
		}
		for _, bond := range bonds {
			exists, err := BondDataExists(bond.SecurityCode)
			if err != nil {
				log.Printf("Error checking bond data exists: %v\n", err)
				return
			}
			if !exists {
				for _, group := range groups {
					msg := model.Reply{
						ReplyMsg:       fmt.Sprintf("号外号外，%s开始申购了", bond.SecurityNameAbbr),
						ReferOriginMsg: false,
						FromMsg: model.Message{
							GroupInfo: model.GroupInfo{
								GroupId: int64(group),
							},
						},
					}
					action.ActionManager.SendMsg(&msg)
				}
			}
			AddBondData(bond)
		}
	})
}
