package base

import (
	"Server-Core/Server/Base/Log"
	"database/sql"
	"fmt"
	_ "github.com/go-sql-driver/mysql"
	"github.com/jmoiron/sqlx"
	"time"
)

type DBInit struct {
	Host     string
	Port     string
	User     string
	Password string
	DBName   string
}

type Db struct {
	sourceName string
	conn       *sqlx.DB
}

func (db *Db) Create(init *DBInit) {
	db.sourceName = fmt.Sprintf("%s:%s@tcp(%s:%s)/%s?readTimeout=5s&writeTimeout=5s", init.User, init.Password, init.Host, init.Port, init.DBName)
	db.connect()
}

func (db *Db) connect() {
	c, err := sqlx.Open("mysql", db.sourceName)
	if err != nil {
		log.Error("DB连接失败 err:%s", err.Error())
	}
	db.conn = c
	err = db.conn.Ping()
	if err != nil {
		log.Error("DB Ping Error:%s", err.Error())
	}

	db.conn.SetConnMaxLifetime(time.Minute * 3)
	db.conn.SetMaxOpenConns(3)
	db.conn.SetMaxIdleConns(3)
}

func (db *Db) reconnect() {
	err := db.conn.Ping()
	if err != nil {
		log.Warn("DB Ping Error, Try Reconnect error:%s", err.Error())
		db.conn.Close()
		db.connect()
	}
}

func (db *Db) Get(dest interface{}, query string, args ...interface{}) {
	db.reconnect()
	error := db.conn.Get(dest, query, args...)
	if error != nil && error != sql.ErrNoRows {
		log.Error("DB Get query:%s Error:%s", query, error.Error())
	}
}

func (db *Db) Insert(query string, args ...interface{}) int64 {
	db.reconnect()
	result, err := db.conn.Exec(query, args...)
	if err != nil {
		log.Error("DB Insert query:%s Error:%s", query, err.Error())
		return 0
	}

	id, _ := result.LastInsertId()
	return id
}

func (db *Db) Query(query string, args ...interface{}) *sql.Rows {
	db.reconnect()
	rows, err := db.conn.Query(query, args...)
	if err != nil {
		log.Error("DB Query query:%s Error:%s", query, err.Error())
		return nil
	}
	return rows
}

func (db *Db) Update(query string, args ...interface{}) {
	db.reconnect()
	_, err := db.conn.Exec(query, args...)
	if err != nil {
		log.Error("DB Query query:%s Error:%s", query, err.Error())
	}
}

func (db *Db) Delete(query string, args ...interface{}) {
	db.reconnect()
	_, err := db.conn.Exec(query, args...)
	if err != nil {
		log.Error("DB Remove query:%s Error:%s", query, err.Error())
	}
}

func (db *Db) Release() {
	db.conn.Close()
}
