package models

import (
	"database/sql"
	"time"

	"mengpost-backend/database"
)

// Account 邮箱账户（basic 为密码；oauth_microsoft 使用刷新令牌）.
type Account struct {
	ID                int64     `json:"id"`
	Name              string    `json:"name"`
	Email             string    `json:"email"`
	Password          string    `json:"password,omitempty"`
	SMTPHost          string    `json:"smtp_host"`
	SMTPPort          int       `json:"smtp_port"`
	IMAPHost          string    `json:"imap_host"`
	IMAPPort          int       `json:"imap_port"`
	UseTLS            bool      `json:"use_tls"`
	AuthType          string    `json:"auth_type"`
	OAuthRefreshToken string    `json:"-"`
	CreatedAt         time.Time `json:"created_at"`
}

func readAuthType(ns sql.NullString) string {
	if ns.Valid && ns.String != "" {
		return ns.String
	}
	return AuthTypeBasic
}

func ListAccounts() ([]Account, error) {
	rows, err := database.DB.Query(`
		SELECT id,name,email,smtp_host,smtp_port,imap_host,imap_port,use_tls,
		       IFNULL(auth_type,'basic'), created_at
		FROM accounts ORDER BY id DESC`)
	if err != nil {
		return nil, err
	}
	defer rows.Close()
	var out []Account
	for rows.Next() {
		var a Account
		var tls int
		var authType sql.NullString
		if err := rows.Scan(&a.ID, &a.Name, &a.Email, &a.SMTPHost, &a.SMTPPort, &a.IMAPHost, &a.IMAPPort, &tls, &authType, &a.CreatedAt); err != nil {
			return nil, err
		}
		a.UseTLS = tls == 1
		a.AuthType = readAuthType(authType)
		out = append(out, a)
	}
	return out, nil
}

func scanFullAccount(row *sql.Row) (*Account, error) {
	var a Account
	var tls int
	var authType, oauthRefresh sql.NullString
	err := row.Scan(&a.ID, &a.Name, &a.Email, &a.Password, &a.SMTPHost, &a.SMTPPort, &a.IMAPHost, &a.IMAPPort, &tls, &authType, &oauthRefresh, &a.CreatedAt)
	if err != nil {
		return nil, err
	}
	a.UseTLS = tls == 1
	a.AuthType = readAuthType(authType)
	if oauthRefresh.Valid {
		a.OAuthRefreshToken = oauthRefresh.String
	}
	return &a, nil
}

func GetAccount(id int64) (*Account, error) {
	row := database.DB.QueryRow(`
		SELECT id,name,email,password,smtp_host,smtp_port,imap_host,imap_port,use_tls,
		       IFNULL(auth_type,'basic'), oauth_refresh_token, created_at
		FROM accounts WHERE id=?`, id)
	return scanFullAccount(row)
}

func GetAccountByEmail(email string) (*Account, error) {
	row := database.DB.QueryRow(`
		SELECT id,name,email,password,smtp_host,smtp_port,imap_host,imap_port,use_tls,
		       IFNULL(auth_type,'basic'), oauth_refresh_token, created_at
		FROM accounts WHERE email=?`, email)
	return scanFullAccount(row)
}

func CreateAccount(a *Account) error {
	if a.AuthType == "" {
		a.AuthType = AuthTypeBasic
	}
	tls := 0
	if a.UseTLS {
		tls = 1
	}
	var oauth any
	if a.OAuthRefreshToken != "" {
		oauth = a.OAuthRefreshToken
	}
	res, err := database.DB.Exec(
		`INSERT INTO accounts(name,email,password,smtp_host,smtp_port,imap_host,imap_port,use_tls,auth_type,oauth_refresh_token)
		 VALUES(?,?,?,?,?,?,?,?,?,?)`,
		a.Name, a.Email, a.Password, a.SMTPHost, a.SMTPPort, a.IMAPHost, a.IMAPPort, tls, a.AuthType, oauth,
	)
	if err != nil {
		return err
	}
	id, _ := res.LastInsertId()
	a.ID = id
	return nil
}

func UpdateAccount(a *Account) error {
	tls := 0
	if a.UseTLS {
		tls = 1
	}
	if a.AuthType == "" {
		a.AuthType = AuthTypeBasic
	}
	_, err := database.DB.Exec(
		`UPDATE accounts SET name=?,email=?,password=COALESCE(NULLIF(?, ''), password),smtp_host=?,smtp_port=?,imap_host=?,imap_port=?,use_tls=?,auth_type=?,
		 oauth_refresh_token=COALESCE(NULLIF(?, ''), oauth_refresh_token) WHERE id=?`,
		a.Name, a.Email, a.Password, a.SMTPHost, a.SMTPPort, a.IMAPHost, a.IMAPPort, tls, a.AuthType,
		a.OAuthRefreshToken, a.ID,
	)
	return err
}

func UpdateAccountOAuthRefresh(id int64, refresh string) error {
	_, err := database.DB.Exec(`UPDATE accounts SET oauth_refresh_token=? WHERE id=?`, refresh, id)
	return err
}

func DeleteAccount(id int64) error {
	_, err := database.DB.Exec(`DELETE FROM accounts WHERE id=?`, id)
	return err
}
