package model

import (
	"crypto/md5"
	"database/sql"
	"errors"
	"fmt"
	"time"
)

type Accounts struct {
	Model
}

type AccountsRow struct {
	Id        int64
	Account   string
	Name      string
	Password  string
	LastLogin int64
	IsSuper   bool
	Disabled  bool
}

func NewAccounts(db *sql.DB) *Accounts {
	return &Accounts{Model{db: db}}
}

func PasswordConvert(pwd string) string {
	pwdMd5 := fmt.Sprintf("%x", md5.Sum([]byte(pwd)))
	return fmt.Sprintf("%x", md5.Sum([]byte(fmt.Sprintf("^redisdog|%s|pwd$", pwdMd5))))
}

func (m *Accounts) Insert(row *AccountsRow) (int64, error) {
	if row.Account == "" {
		return 0, errors.New("账号不能为空")
	}
	if len(row.Password) < 6 {
		return 0, errors.New("密码长度不能小于6")
	}
	disabledInt := 0
	if row.Disabled {
		disabledInt = 1
	}
	passwordEnc := PasswordConvert(row.Password)
	ret, err := m.db.Exec(`INSERT INTO accounts(account,name,password,is_super,disabled) VALUES(?,?,?,?,?)`, row.Account, row.Name, passwordEnc, row.IsSuper, disabledInt)
	if err != nil {
		return 0, nil
	}
	return ret.LastInsertId()
}

func (m *Accounts) Delete(id int64) (int64, error) {
	if id <= 0 {
		return 0, errors.New("ID必须是大于0的整数")
	}
	ret, err := m.db.Exec("DELETE FROM accounts WHERE id=?", id)
	if err != nil {
		return 0, err
	}
	return ret.RowsAffected()
}

func (m *Accounts) Update(row *AccountsRow) (int64, error) {
	if row.Id <= 0 {
		return 0, errors.New("ID必须是大于0的整数")
	}
	if row.Account == "" {
		return 0, errors.New("账号不能为空")
	}
	disabledInt := 0
	if row.Disabled {
		disabledInt = 1
	}
	ret, err := m.db.Exec(`UPDATE accounts SET account=?,name=?,is_super=?,disabled=? WHERE id=?`, row.Account, row.Name, row.IsSuper, disabledInt, row.Id)
	if err != nil {
		return 0, err
	}
	return ret.RowsAffected()
}

func (m *Accounts) UpdatePassword(id int64, password string) (int64, error) {
	if id <= 0 {
		return 0, errors.New("ID必须是大于0的整数")
	}
	if len(password) < 6 {
		return 0, errors.New("密码长度不能小于6")
	}
	passwordEnc := PasswordConvert(password)
	ret, err := m.db.Exec(`UPDATE accounts SET password=? WHERE id=?`, passwordEnc, id)
	if err != nil {
		return 0, err
	}
	return ret.RowsAffected()
}

func (m *Accounts) Get(id int64) (*AccountsRow, error) {
	if id <= 0 {
		return nil, errors.New("ID必须是大于0的整数")
	}
	result := m.db.QueryRow("SELECT id,account,name,last_login,is_super,disabled FROM accounts WHERE id=?", id)
	row := AccountsRow{}
	err := result.Scan(
		&row.Id,
		&row.Account,
		&row.Name,
		&row.LastLogin,
		&row.IsSuper,
		&row.Disabled,
	)
	if err != nil {
		if err == sql.ErrNoRows {
			return nil, errors.New("记录不存在")
		} else {
			return nil, err
		}
	} else {
		return &row, nil
	}
}

func (m *Accounts) GetAll() ([]*AccountsRow, error) {
	result, err := m.db.Query(`SELECT id,account,name,last_login,is_super,disabled FROM accounts ORDER BY id`)
	if err != nil {
		return nil, err
	}
	rows := make([]*AccountsRow, 0)
	for result.Next() {
		row := AccountsRow{}
		err = result.Scan(
			&row.Id,
			&row.Account,
			&row.Name,
			&row.LastLogin,
			&row.IsSuper,
			&row.Disabled,
		)
		if err != nil {
			continue
		}
		rows = append(rows, &row)
	}
	return rows, nil
}

func (m *Accounts) Login(account, password string) (*AccountsRow, error) {
	if account == "" {
		return nil, errors.New("账号不能为空")
	}
	if len(password) < 6 {
		return nil, errors.New("密码长度不能小于6")
	}
	passwordEnc := PasswordConvert(password)
	result := m.db.QueryRow("SELECT id,account,name,last_login,is_super,disabled FROM accounts WHERE account=? AND password=? LIMIT 1", account, passwordEnc)
	row := AccountsRow{}
	err := result.Scan(
		&row.Id,
		&row.Account,
		&row.Name,
		&row.LastLogin,
		&row.IsSuper,
		&row.Disabled,
	)
	if err != nil {
		if err == sql.ErrNoRows {
			return nil, errors.New("用户名或密码错误")
		} else {
			return nil, err
		}
	} else if row.Disabled {
		return nil, errors.New("账号已被禁用")
	} else {
		m.db.Exec("UPDATE last_login=? WHERE id=?", time.Now().Unix(), row.Id)
		return &row, nil
	}
}
