package core

import (
	"fmt"
	"strings"

	"github.com/linlexing/dbx/data"
	"github.com/linlexing/dbx/render"

	"github.com/linlexing/dbx/ddb"
)

//RemoveNotExistsCheckResult 删除记录已经不存在的审核结果
func RemoveNotExistsCheckResult(db ddb.DB, tableName string) error {
	tab, err := ddb.OpenTable(db, tableName)
	if err != nil {
		return err
	}
	pksTerm := []string{}
	for _, one := range tab.PrimaryKeys {
		pksTerm = append(pksTerm, fmt.Sprintf("CR_%s.%s=%[1]s.%[2]s", tableName, one))
	}
	_, err = db.Exec(fmt.Sprintf("delete from CR_%s where not exists(select 1 from %[1]s where %s)",
		tableName, strings.Join(pksTerm, " and\n")))
	return err
}

//BatchCheck 批量审核一个表，传入指定的主键select，并按顺序给出主键字段名
func BatchCheck(db ddb.DB, tableName, selectPKSQL string, pkNames []string, user *User) (int64, error) {
	tab, err := ddb.OpenTable(db, tableName)
	if err != nil {
		return -1, err
	}
	insPKSTerm := []string{}
	pksTerm := []string{}
	for i, one := range tab.PrimaryKeys {
		pksTerm = append(pksTerm, fmt.Sprintf("CR_%s.%s=batchdel.%s", tableName, one, pkNames[i]))
		insPKSTerm = append(insPKSTerm, fmt.Sprintf("%s.%s=bb.%s", tableName, one, pkNames[i]))
	}
	//先删除先前的审核结果,注意只能删除本级或上级条件对应的结果
	strSQL := fmt.Sprintf(`delete from CR_%s where 
		exists(select 1 from tablecheck tc where tc.id=CR_%[1]s.checkid and ? like %s) and
		exists(select 1 from (%s) batchdel where %s)`,
		tableName, data.Find(db.DriverName()).Concat("tc.dept", "'%'"),
		selectPKSQL, strings.Join(pksTerm, " and\n"))
	if _, err = db.Exec(strSQL, user.Dept.Code); err != nil {
		return -1, err
	}
	//再调入所有的审核条件
	chks := []*TableCheck{}
	//闭包是为了rows.Close,游标不关闭，操作其他可能有些数据库会异常
	if err := func() error {
		rows, err := db.Query(fmt.Sprintf(
			"select id,label,tablename,must,condition,referfields,detailtmpl,dept "+
				"from tablecheck where tablename=? and ? like %s",
			data.Find(db.DriverName()).Concat("dept", "'%'")), tableName, user.Dept.Code)
		if err != nil {
			return err
		}
		defer rows.Close()
		for rows.Next() {
			chk := &TableCheck{}
			if err = rows.Scan(&chk.ID, &chk.Label, &chk.TableName, &chk.Must, &chk.Condition,
				&chk.ReferFields, &chk.DetailTmpl, &chk.Dept); err != nil {
				LOG.Panic(err)
			}
			//批量暂时不支持审核差错信息detail
			// chk.loadDetailTmpl()
			chks = append(chks, chk)
		}
		return nil
	}(); err != nil {
		return -1, err
	}
	icount := int64(0)
	for _, one := range chks {
		strWhere, err := render.RenderSQL(one.Condition.String,
			map[string]interface{}{"User": user})
		if err != nil {
			return 0, err
		}
		strSQL = fmt.Sprintf(
			`insert into CR_%s(checkid,%s)select ?,%[2]s from %[1]s where 
				exists(select 1 from (%[3]s) bb where %s) and (%s)`,
			tableName, strings.Join(tab.PrimaryKeys, ","), selectPKSQL,
			strings.Join(insPKSTerm, " and\n"), strWhere)
		if sr, err := db.Exec(strSQL, one.ID); err != nil {
			return -1, err
		} else if ic, err := sr.RowsAffected(); err != nil {

			return -1, err
		} else {
			icount += ic
		}
	}
	return icount, nil
}
