package tables

import (
	"Wine-Server/utils"
	"database/sql"
)

type WorkerTable struct {
	Id    string
	First utils.TimeType
	Last  utils.TimeType

	Name     string
	Phone    string
	Password string
	Manager  string

	Count uint32
	Cost  uint32
}

func CreateWorkerTable() error {
	SQL := "CREATE TABLE IF NOT EXISTS `worker`(" +
		"`id` VARCHAR(16) PRIMARY KEY NOT NULL," +
		"`first` DATETIME DEFAULT CURRENT_TIMESTAMP," +
		"`last` DATETIME DEFAULT CURRENT_TIMESTAMP," +
		"`name` VARCHAR(16) NOT NULL," +
		"`phone` VARCHAR(11) NOT NULL," +
		"`password` VARCHAR(128) NOT NULL," +
		"`manager` VARCHAR(16) DEFAULT ''," +
		"`count` INT UNSIGNED DEFAULT 0," +
		"`cost` INT UNSIGNED DEFAULT 0);"
	_, err := utils.Mysql.Exec(SQL)
	return err
}

func (row *WorkerTable) Insert() error {
	SQL := "INSERT INTO `worker`(`id`,`name`,`phone`,`password`) VALUES(?,?,?,?);"
	pre, err := utils.Mysql.Prepare(SQL)
	if err != nil {
		return err
	}
	_, err = pre.Exec(row.Id, row.Name, row.Phone, row.Password)
	return err
}

func (row *WorkerTable) Delete() error {
	pre, err := utils.Mysql.Prepare("DELETE FROM `worker` WHERE `id`=?;")
	if err != nil {
		return err
	}
	_, err = pre.Exec(row.Id)
	return err
}

func (row *WorkerTable) Update(args utils.JsonType) error {
	keys, values := utils.UnZip(args)
	SQL := utils.Format("UPDATE `worker` SET %s WHERE `id`='%s';", utils.SqlFields(keys), row.Id)
	pre, err := utils.Mysql.Prepare(SQL)
	if err != nil {
		return err
	}
	_, err = pre.Exec(values...)
	return err
}

func (row *WorkerTable) UpdateSelf() error {
	SQL := "UPDATE `worker` SET `last`=?,`name`=?,`phone`=?,`password`=?,`manager`=?,`count`=?,`cost`=? WHERE `id`=?;"
	pre, err := utils.Mysql.Prepare(SQL)
	if err != nil {
		return err
	}
	row.Last = utils.TimeNow()
	_, err = pre.Exec(row.Last, row.Name, row.Phone, row.Password, row.Manager, row.Count, row.Cost, row.Id)
	return err
}

func (row *WorkerTable) Get() error {
	SQL := "SELECT `first`,`last`,`name`,`phone`,`password`,`manager`,`count`,`cost` FROM `worker` WHERE `id`=?;"
	pre, err := utils.Mysql.Prepare(SQL)
	if err != nil {
		return err
	}
	err = pre.QueryRow(row.Id).Scan(
		&row.First, &row.Last, &row.Name, &row.Phone,
		&row.Password, &row.Count, &row.Cost,
	)
	return err
}

func (row *WorkerTable) GetByPhone() error {
	SQL := "SELECT `id`,`first`,`last`,`name`,`password`,`manager`,`count`,`cost` FROM `worker` WHERE `phone`=? LIMIT 1;"
	pre, err := utils.Mysql.Prepare(SQL)
	if err != nil {
		return err
	}
	err = pre.QueryRow(row.Phone).Scan(
		&row.Id, &row.First, &row.Last, &row.Name,
		&row.Password, &row.Manager, &row.Count, &row.Cost,
	)
	return err
}

func WorkerQuery(manager, cond string, limit, page int) (int, []utils.JsonType, error) {
	SQL := "none"
	if manager == "" { // any
		SQL = utils.Format(
			"SELECT COUNT(`id`) AS `total` FROM `worker` WHERE `name` LIKE '%%%s%%' OR `phone` LIKE '%%%s%%';",
			cond, cond,
		)
	} else { // one
		SQL = utils.Format(
			"SELECT COUNT(`id`) AS `total` FROM `worker` WHERE `manager`='%s' AND (`name` LIKE '%%%s%%' OR `phone` LIKE '%%%s%%');",
			manager, cond, cond,
		)
	}
	total := 0
	err := utils.Mysql.QueryRow(SQL).Scan(&total)
	if err != nil {
		return 0, nil, err
	}
	if total == 0 {
		return 0, []utils.JsonType{}, err
	}
	if manager == "" { // any
		SQL = utils.Format(
			"SELECT w.`id`,w.`first`,w.`last`,w.`name`,w.`phone`,w.`count`,w.`cost`,m.`id`,m.`name` "+
				"FROM `worker` AS w LEFT JOIN `manager` AS m "+
				"ON w.`manager`=m.`id` WHERE w.`name` LIKE '%%%s%%' OR w.`phone` LIKE '%%%s%%' LIMIT %d OFFSET %d;",
			cond, cond, limit, (page-1)*limit,
		)
	} else { // one
		SQL = utils.Format(
			"SELECT w.`id`,w.`first`,w.`last`,w.`name`,w.`phone`,w.`count`,w.`cost`,m.`id`,m.`name` "+
				"FROM `worker` AS w LEFT JOIN `manager` AS m "+
				"ON w.`manager`=m.`id` WHERE w.`manager`='%s' AND (w.`name` LIKE '%%%s%%' OR w.`phone` LIKE '%%%s%%') LIMIT %d OFFSET %d;",
			manager, cond, cond, limit, (page-1)*limit,
		)
	}

	var rows *sql.Rows
	rows, err = utils.Mysql.Query(SQL)
	if err != nil {
		return 0, nil, err
	}
	res := make([]utils.JsonType, 0)
	for rows.Next() {
		var worker WorkerTable
		name := ""
		_ = rows.Scan(&worker.Id, &worker.First, &worker.Last, &worker.Name, &worker.Phone, &worker.Count, &worker.Cost, &worker.Manager, &name)
		res = append(res, utils.JsonType{
			"id": worker.Id, "first": worker.First, "last": worker.Last, "name": worker.Name, "phone": worker.Phone,
			"count": worker.Count, "cost": worker.Cost, "manager": utils.JsonType{"id": worker.Manager, "name": name},
		})
	}
	_ = rows.Close()
	return total, res, nil
}

func WorkerQueryForAdmin(manager, cond string, limit, page int) (int, []utils.JsonType, error) {
	SQL := utils.Format(
		"SELECT COUNT(`id`) AS `total` FROM `worker` WHERE `manager`='%s' AND (`name` LIKE '%%%s%%' OR `phone` LIKE '%%%s%%');",
		manager, cond, cond,
	)
	total := 0
	err := utils.Mysql.QueryRow(SQL).Scan(&total)
	if err != nil {
		return 0, nil, err
	}
	if total == 0 {
		return 0, []utils.JsonType{}, err
	}
	SQL = utils.Format(
		"SELECT `id`,`first`,`last`,`name`,`phone`,`count`,`cost` FROM `worker` "+
			"WHERE `manager`='%s' AND (`name` LIKE '%%%s%%' OR `phone` LIKE '%%%s%%') LIMIT %d OFFSET %d;",
		manager, cond, cond, limit, (page-1)*limit,
	)
	var rows *sql.Rows
	rows, err = utils.Mysql.Query(SQL)
	if err != nil {
		return 0, nil, err
	}
	res := make([]utils.JsonType, 0)
	for rows.Next() {
		var worker WorkerTable
		_ = rows.Scan(&worker.Id, &worker.First, &worker.Last, &worker.Name, &worker.Phone, &worker.Count, &worker.Cost)
		res = append(res, utils.JsonType{
			"id": worker.Id, "first": worker.First, "last": worker.Last, "name": worker.Name,
			"phone": worker.Phone, "count": worker.Count, "cost": worker.Cost,
		})
	}
	_ = rows.Close()
	return total, res, nil
}

func WorkersDelete(ids []string) error {
	SQL := utils.Format("DELETE FROM `worker` WHERE `id` IN (%s);", utils.SqlStringListJoin(ids))
	_, err := utils.Mysql.Exec(SQL)
	return err
}
