package common

import (
	"dbweb/core"
	"fmt"
	"net/url"
	"time"

	"github.com/linlexing/dbx/ddb"

	"dbweb/lib/bill"

	"github.com/linlexing/dbx/common"
	"github.com/linlexing/dbx/data"
	"github.com/linlexing/dbx/scan"
	"github.com/linlexing/dbx/schema"
)

type myTable struct{}

const (
	modelMyTableName = "MYTABLE"
)

type modelMyTable struct {
	UserName   string    `dbx:"STR(50) PRIMARY KEY"`
	Name       string    `dbx:"STR(50) PRIMARY KEY"`
	DBName     string    `dbx:"STR(50)"`
	TableName  string    `dbx:"STR(50) NOT NULL"`
	CreateTime time.Time `dbx:"DATE"`
}

func init() {
	core.RegisterModel(modelMyTable{}, 2, false, modelMyTableName)
	core.RegisterBill("mytable", new(myTable), modelMyTableName)
}

func (m *myTable) Get(p *core.BillGetHandleArgs) {
	var err error
	list := []map[string]interface{}{
		map[string]interface{}{
			"Value": "",
			"Text":  "(当前数据库)",
		}}
	for _, v := range core.OuterDBList(p.DB) {
		list = append(list, map[string]interface{}{
			"Value": p.User.EncodeQueryValue(v.Name),
			"Text":  v.Name,
		})
	}
	p.Field("DBNAME").More["Options"] = list
	rec := &modelMyTable{}
	if err = p.Record.Scan(rec); err != nil {
		core.LOG.Panic(rec)
	}

	if p.Param.Operate == "add" {
		if name, err := ddb.GetTempTableName(core.LoadOuterDB(p.DB, rec.DBName), "U"); err != nil {
			core.LOG.Panic(err)
		} else {
			rec.TableName = name
		}
	}
	eleName := ""
	switch p.Param.Operate {
	case "edit", "add":
		eleName = "edittabledef_noname"
	case "delete", "browse":
		eleName = "browsetabledef"
	default:
		core.LOG.Panic("not impl")
	}
	strURL := core.ElementUrl(eleName, rec.TableName)
	u, _ := url.Parse(strURL)
	q := u.Query()
	q.Add("db", p.User.EncodeQueryValue(rec.DBName))
	u.RawQuery = q.Encode()

	p.More["TableDefineUrl"] = p.User.Sign(u.String())
	p.Record, err = bill.ParseRecord(rec)
	if err != nil {
		core.LOG.Panic(err)
	}
	p.HTML()
}
func (m *myTable) Delete(p *core.BillDeleteHandleArgs) {
	rec := &modelMyTable{}
	if err := p.OldRecord.Scan(rec); err != nil {
		core.LOG.Panic(err)
	}
	p.Remove()
	db := core.LoadOuterDB(p.DB, rec.DBName)
	if _, err := db.Exec("drop table " + rec.TableName); err != nil {
		core.LOG.Panic(err)
	}
	core.LOG.Println("drop table " + rec.TableName)
	return
}

//CreateMyTableAs 创建一个附加表
func CreateMyTableAs(db ddb.DB, name, dataDBName, outDBName, typeTableName string,
	typeColumns []*scan.ColumnType, query string, pks []string, user *core.User,
	progressFunc func(string)) (string, error) {
	//如果有重名，则提示
	md := core.LoadModel(modelMyTableName)
	if exists, err := md.KeyExists(user.Name, name); err != nil {
		return "", err
	} else if exists {
		return "", fmt.Errorf("the name:%s is exists", name)
	}
	rec := modelMyTable{
		UserName:   user.Name,
		DBName:     outDBName,
		Name:       name,
		CreateTime: time.Now(),
	}
	var err error
	outDB := core.LoadOuterDB(db, outDBName)
	//确定名称
	if rec.TableName, err = ddb.GetTempTableName(outDB, "U"); err != nil {
		return "", err
	}
	//如果是同一个数据库，则用直接的createtableas
	if dataDBName == outDBName {
		if err := ddb.RunAtTx(outDB, func(tx ddb.Txer) error {
			list, err := schema.Find(tx.DriverName()).CreateTableAsSQL(tx, rec.TableName, query, pks)
			if err != nil {
				return err
			}
			return common.BatchRun(tx, list)
		}); err != nil {
			return "", err
		}
	} else {
		dataDB := core.LoadOuterDB(db, dataDBName)
		typeTable, err := schema.Find(dataDB.DriverName()).OpenTable(dataDB, typeTableName)
		if err != nil {
			return "", err
		}
		//创建表
		outTable := schema.NewTable(rec.TableName)
		newCols := []*schema.Column{}
		for _, col := range typeColumns {
			var newCol *schema.Column
			if findCol := typeTable.ColumnByName(col.Name); findCol != nil {
				newCol = findCol
			} else {
				newCol := &schema.Column{
					Name: col.Name,
					Type: col.Type,
				}
				//如果是字符串，则固定为300大小
				if col.Type == schema.TypeString {
					newCol.MaxLength = 300
				}
			}
			newCols = append(newCols, newCol)
		}
		outTable.Columns = newCols
		outTable.PrimaryKeys = pks
		if err = outTable.Update(outDB.DriverName(), outDB); err != nil {
			return "", err
		}
		//然后导入数据
		outDataTable := data.NewTable(outDB.DriverName(), outDB, outTable)
		if _, err = outDataTable.ImportFrom(dataDB, progressFunc, query); err != nil {
			return "", err
		}
	}
	if err = md.Insert(rec); err != nil {
		return "", err
	}
	return rec.TableName, nil
}
