package services

import (
	"crypto/tls"
	"encoding/json"
	"fmt"
	"io"
	"net/http"
	"net/http/cookiejar"
	"net/url"
	"strconv"
	"strings"
	"time"

	"lan-manager/server/db"
	"lan-manager/server/models"
	"lan-manager/server/utils"
)

type PVEClient struct {
	NodeName   string
	Host        string
	Port        int
	Username    string
	Password    string
	VerifySSL   bool
	CSRFToken   string
	Cookie      string
	httpClient  *http.Client
}

func NewPVEClient(host *models.PVEHost, password string) *PVEClient {
	jar, _ := cookiejar.New(nil)
	client := &http.Client{
		Jar: jar,
		Timeout: 30 * time.Second,
	}
	if !host.VerifySSL {
		client.Transport = &http.Transport{
			TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
		}
	}
	return &PVEClient{
		Host:       host.Hostname,
		Port:       host.Port,
		Username:   host.Username,
		Password:   password,
		NodeName:   host.NodeName,
		VerifySSL:  host.VerifySSL,
		httpClient: client,
	}
}

func (c *PVEClient) baseURL() string {
	// PVE 始终使用 HTTPS，verify_ssl 只控制是否验证证书
	return fmt.Sprintf("https://%s:%d", c.Host, c.Port)
}

// Login 获取 PVE 认证ticket
func (c *PVEClient) Login() error {
	loginURL := c.baseURL() + "/api2/json/access/ticket"
	formData := url.Values{}
	formData.Set("username", c.Username)
	formData.Set("password", c.Password)

	req, err := http.NewRequest("POST", loginURL, strings.NewReader(formData.Encode()))
	if err != nil {
		return err
	}
	req.Header.Set("Content-Type", "application/x-www-form-urlencoded")

	resp, err := c.httpClient.Do(req)
	if err != nil {
		return err
	}
	defer resp.Body.Close()

	if resp.StatusCode != http.StatusOK {
		return fmt.Errorf("login failed, status: %d", resp.StatusCode)
	}

	var result struct {
		Data struct {
			CSRFToken string `json:"CSRFPreventionToken"`
			Ticket    string `json:"ticket"`
		} `json:"data"`
	}

	body, err := io.ReadAll(resp.Body)
	if err != nil {
		return fmt.Errorf("read login response failed: %v", err)
	}

	if err := json.Unmarshal(body, &result); err != nil {
		return fmt.Errorf("decode login response failed: %v, body: %s", err, string(body))
	}

	c.CSRFToken = result.Data.CSRFToken
	c.Cookie = "PVEAuthCookie=" + result.Data.Ticket
	return nil
}

// GetVMStatus 获取虚拟机状态
func (c *PVEClient) GetVMStatus(vmid string) (*models.PVEVMStatus, error) {
	if c.CSRFToken == "" {
		if err := c.Login(); err != nil {
			return nil, err
		}
	}

	// 获取 node 名称（通常是 pve）
	statusURL := c.baseURL() + "/api2/json/nodes/" + c.NodeName + "/qemu/" + vmid + "/status/current"

	req, err := http.NewRequest("GET", statusURL, nil)
	if err != nil {
		return nil, err
	}
	req.Header.Set("Cookie", c.Cookie)
	req.Header.Set("CSRFPreventionToken", c.CSRFToken)

	resp, err := c.httpClient.Do(req)
	if err != nil {
		return nil, err
	}
	defer resp.Body.Close()

	if resp.StatusCode == 401 {
		// token 过期，重新登录
		if err := c.Login(); err != nil {
			return nil, err
		}
		return c.GetVMStatus(vmid)
	}

	if resp.StatusCode != http.StatusOK {
		return nil, fmt.Errorf("get vm status failed, status: %d", resp.StatusCode)
	}

	body, err := io.ReadAll(resp.Body)
	if err != nil {
		return nil, fmt.Errorf("read body failed: %v", err)
	}

	var result struct {
		Data struct {
			Status      string  `json:"status"`
			Uptime      int64   `json:"uptime"`
			CPU         float64 `json:"cpu"`
			MemoryUsed  int64   `json:"mem"`
			MemoryTotal int64   `json:"maxmem"`
		} `json:"data"`
	}

	if err := json.Unmarshal(body, &result); err != nil {
		return nil, fmt.Errorf("decode failed: %v, body: %s", err, string(body))
	}

	return &models.PVEVMStatus{
		Status:      result.Data.Status,
		Uptime:      result.Data.Uptime,
		CPU:         result.Data.CPU * 100,
		MemoryUsed:  result.Data.MemoryUsed,
		MemoryTotal: result.Data.MemoryTotal,
	}, nil
}

// StartVM 启动虚拟机
func (c *PVEClient) StartVM(vmid string) error {
	if c.CSRFToken == "" {
		if err := c.Login(); err != nil {
			return err
		}
	}

	startURL := c.baseURL() + "/api2/json/nodes/" + c.NodeName + "/qemu/" + vmid + "/status/start"

	req, err := http.NewRequest("POST", startURL, nil)
	if err != nil {
		return err
	}
	req.Header.Set("Cookie", c.Cookie)
	req.Header.Set("CSRFPreventionToken", c.CSRFToken)

	resp, err := c.httpClient.Do(req)
	if err != nil {
		return err
	}
	defer resp.Body.Close()

	if resp.StatusCode == 401 {
		if err := c.Login(); err != nil {
			return err
		}
		return c.StartVM(vmid)
	}

	if resp.StatusCode != http.StatusOK {
		body, _ := io.ReadAll(resp.Body)
		return fmt.Errorf("start vm failed, status: %d, body: %s", resp.StatusCode, string(body))
	}

	return nil
}

// StopVM 停止虚拟机
func (c *PVEClient) StopVM(vmid string) error {
	if c.CSRFToken == "" {
		if err := c.Login(); err != nil {
			return err
		}
	}

	stopURL := c.baseURL() + "/api2/json/nodes/" + c.NodeName + "/qemu/" + vmid + "/status/stop"

	req, err := http.NewRequest("POST", stopURL, nil)
	if err != nil {
		return err
	}
	req.Header.Set("Cookie", c.Cookie)
	req.Header.Set("CSRFPreventionToken", c.CSRFToken)

	resp, err := c.httpClient.Do(req)
	if err != nil {
		return err
	}
	defer resp.Body.Close()

	if resp.StatusCode == 401 {
		if err := c.Login(); err != nil {
			return err
		}
		return c.StopVM(vmid)
	}

	if resp.StatusCode != http.StatusOK {
		body, _ := io.ReadAll(resp.Body)
		return fmt.Errorf("stop vm failed, status: %d, body: %s", resp.StatusCode, string(body))
	}

	return nil
}

// GetVMList 获取虚拟机列表
func (c *PVEClient) GetVMList() ([]struct {
	VMID   string `json:"vmid"`
	Name   string `json:"name"`
	Status string `json:"status"`
}, error) {
	if c.CSRFToken == "" {
		if err := c.Login(); err != nil {
			return nil, err
		}
	}

	listURL := c.baseURL() + "/api2/json/nodes/" + c.NodeName + "/qemu"

	req, err := http.NewRequest("GET", listURL, nil)
	if err != nil {
		return nil, err
	}
	req.Header.Set("Cookie", c.Cookie)
	req.Header.Set("CSRFPreventionToken", c.CSRFToken)

	resp, err := c.httpClient.Do(req)
	if err != nil {
		return nil, err
	}
	defer resp.Body.Close()

	if resp.StatusCode != http.StatusOK {
		body, _ := io.ReadAll(resp.Body)
		return nil, fmt.Errorf("get vm list failed, status: %d, body: %s", resp.StatusCode, string(body))
	}

	body, err := io.ReadAll(resp.Body)
	if err != nil {
		return nil, fmt.Errorf("read vm list body failed: %v", err)
	}

	var result struct {
		Data []struct {
			VMID   int    `json:"vmid"`
			Name   string `json:"name"`
			Status string `json:"status"`
		} `json:"data"`
	}

	if err := json.Unmarshal(body, &result); err != nil {
		return nil, fmt.Errorf("decode vm list failed: %v, body: %s", err, string(body))
	}

	// vmid 是 int，转换为 string
	vms := make([]struct {
		VMID   string `json:"vmid"`
		Name   string `json:"name"`
		Status string `json:"status"`
	}, len(result.Data))
	for i, vm := range result.Data {
		vms[i] = struct {
			VMID   string `json:"vmid"`
			Name   string `json:"name"`
			Status string `json:"status"`
		}{
			VMID:   strconv.Itoa(vm.VMID),
			Name:   vm.Name,
			Status: vm.Status,
		}
	}
	return vms, nil
}

// PVEHostService PVE 主机服务
type PVEHostService struct{}

func NewPVEHostService() *PVEHostService {
	return &PVEHostService{}
}

// GetAll 获取所有 PVE 主机
func (s *PVEHostService) GetAll() ([]models.PVEHost, error) {
	rows, err := db.DB.Query(`SELECT id, name, hostname, port, username, node_name, password_enc, verify_ssl, created_at, updated_at FROM pve_hosts ORDER BY id`)
	if err != nil {
		return nil, err
	}
	defer rows.Close()

	hosts := []models.PVEHost{}
	for rows.Next() {
		var h models.PVEHost
		var verifySSL int
		if err := rows.Scan(&h.ID, &h.Name, &h.Hostname, &h.Port, &h.Username, &h.NodeName, &h.PasswordEnc, &verifySSL, &h.CreatedAt, &h.UpdatedAt); err != nil {
			return nil, err
		}
		h.VerifySSL = verifySSL == 1
		hosts = append(hosts, h)
	}
	return hosts, nil
}

// GetByID 根据 ID 获取 PVE 主机
func (s *PVEHostService) GetByID(id int64) (*models.PVEHost, error) {
	var h models.PVEHost
	var verifySSL int
	err := db.DB.QueryRow(`SELECT id, name, hostname, port, username, node_name, password_enc, verify_ssl, created_at, updated_at FROM pve_hosts WHERE id = ?`, id).
		Scan(&h.ID, &h.Name, &h.Hostname, &h.Port, &h.Username, &h.NodeName, &h.PasswordEnc, &verifySSL, &h.CreatedAt, &h.UpdatedAt)
	if err != nil {
		return nil, err
	}
	h.VerifySSL = verifySSL == 1
	return &h, nil
}

// Create 创建 PVE 主机
func (s *PVEHostService) Create(host *models.PVEHost) error {
	// 加密密码
	encPassword, err := utils.Encrypt(host.Password)
	if err != nil {
		return fmt.Errorf("encrypt password failed: %w", err)
	}

	result, err := db.DB.Exec(`INSERT INTO pve_hosts (name, hostname, port, username, node_name, password_enc, verify_ssl) VALUES (?, ?, ?, ?, ?, ?, ?)`,
		host.Name, host.Hostname, host.Port, host.Username, host.NodeName, encPassword, boolToInt(host.VerifySSL))
	if err != nil {
		return err
	}

	id, err := result.LastInsertId()
	if err != nil {
		return err
	}
	host.ID = id
	return nil
}

// Update 更新 PVE 主机
func (s *PVEHostService) Update(host *models.PVEHost) error {
	if host.Password != "" {
		// 密码有更新，重新加密
		encPassword, err := utils.Encrypt(host.Password)
		if err != nil {
			return fmt.Errorf("encrypt password failed: %w", err)
		}
		_, err = db.DB.Exec(`UPDATE pve_hosts SET name=?, hostname=?, port=?, username=?, node_name=?, password_enc=?, verify_ssl=?, updated_at=CURRENT_TIMESTAMP WHERE id=?`,
			host.Name, host.Hostname, host.Port, host.Username, host.NodeName, encPassword, boolToInt(host.VerifySSL), host.ID)
		return err
	}

	_, err := db.DB.Exec(`UPDATE pve_hosts SET name=?, hostname=?, port=?, username=?, node_name=?, verify_ssl=?, updated_at=CURRENT_TIMESTAMP WHERE id=?`,
		host.Name, host.Hostname, host.Port, host.Username, host.NodeName, boolToInt(host.VerifySSL), host.ID)
	return err
}

// Delete 删除 PVE 主机
func (s *PVEHostService) Delete(id int64) error {
	// 先清除关联机器的 PVE 字段
	if _, err := db.DB.Exec(`UPDATE machines SET pve_host_id = NULL, pve_vmid = NULL WHERE pve_host_id = ?`, id); err != nil {
		return err
	}
	_, err := db.DB.Exec(`DELETE FROM pve_hosts WHERE id = ?`, id)
	return err
}

// GetDecryptedPassword 获取解密后的密码
func (s *PVEHostService) GetDecryptedPassword(host *models.PVEHost) (string, error) {
	return utils.Decrypt(host.PasswordEnc)
}

// GetHostStatus 检测 PVE 节点连接状态
func (s *PVEHostService) GetHostStatus(hostID int64) (string, error) {
	host, err := s.GetByID(hostID)
	if err != nil {
		return "offline", err
	}

	password, err := s.GetDecryptedPassword(host)
	if err != nil {
		return "offline", err
	}

	client := NewPVEClient(host, password)
	if err := client.Login(); err != nil {
		return "offline", nil
	}
	return "online", nil
}

// GetHostVMList 获取 PVE 节点上的虚拟机列表
func (s *PVEHostService) GetHostVMList(hostID int64) ([]struct {
	VMID   string `json:"vmid"`
	Name   string `json:"name"`
	Status string `json:"status"`
}, error) {
	host, err := s.GetByID(hostID)
	if err != nil {
		return nil, err
	}

	password, err := s.GetDecryptedPassword(host)
	if err != nil {
		return nil, err
	}

	client := NewPVEClient(host, password)
	return client.GetVMList()
}

// GetVMStatus 获取虚拟机状态
func (s *PVEHostService) GetVMStatus(hostID int64, vmid string) (*models.PVEVMStatus, error) {
	host, err := s.GetByID(hostID)
	if err != nil {
		return nil, err
	}

	password, err := s.GetDecryptedPassword(host)
	if err != nil {
		return nil, err
	}

	client := NewPVEClient(host, password)
	return client.GetVMStatus(vmid)
}

// StartVM 启动虚拟机
func (s *PVEHostService) StartVM(hostID int64, vmid string) error {
	host, err := s.GetByID(hostID)
	if err != nil {
		return err
	}

	password, err := s.GetDecryptedPassword(host)
	if err != nil {
		return err
	}

	client := NewPVEClient(host, password)
	return client.StartVM(vmid)
}

// StopVM 停止虚拟机
func (s *PVEHostService) StopVM(hostID int64, vmid string) error {
	host, err := s.GetByID(hostID)
	if err != nil {
		return err
	}

	password, err := s.GetDecryptedPassword(host)
	if err != nil {
		return err
	}

	client := NewPVEClient(host, password)
	return client.StopVM(vmid)
}

func boolToInt(b bool) int {
	if b {
		return 1
	}
	return 0
}

