package storage

import (
	"crm-go/models"
	"crypto/rand"
	"database/sql"
	"encoding/hex"
	"fmt"
	"strings"
	"time"
)

type mysqlTrialPeriodStorage struct {
	db *sql.DB
}

// NewMySQLTrialPeriodStorage 创建MySQL试用期存储
func NewMySQLTrialPeriodStorage() TrialPeriodStorage {
	return &mysqlTrialPeriodStorage{
		db: GetDB(),
	}
}

func (ts *mysqlTrialPeriodStorage) GetAllTrialPeriods() ([]models.TrialPeriod, error) {
	query := `
		SELECT id, customer_name, COALESCE(source, '') as source, start_time, end_time, is_trial, created_at
		FROM trial_periods 
		ORDER BY created_at DESC
	`

	rows, err := ts.db.Query(query)
	if err != nil {
		return nil, err
	}
	defer rows.Close()

	var trialPeriods []models.TrialPeriod
	for rows.Next() {
		var tp models.TrialPeriod
		var isTrial int

		err := rows.Scan(
			&tp.ID, &tp.CustomerName, &tp.Source, &tp.StartTime,
			&tp.EndTime, &isTrial, &tp.CreatedAt,
		)
		if err != nil {
			return nil, err
		}

		tp.IsTrial = isTrial == 1
		trialPeriods = append(trialPeriods, tp)
	}

	return trialPeriods, rows.Err()
}

func (ts *mysqlTrialPeriodStorage) GetTrialPeriodsByCustomerID(customerID string) ([]models.TrialPeriod, error) {
	query := `
		SELECT id, customer_name, COALESCE(source, '') as source, start_time, end_time, is_trial, created_at
		FROM trial_periods 
		WHERE customer_name = ?
		ORDER BY end_time DESC
	`

	rows, err := ts.db.Query(query, customerID)
	if err != nil {
		return nil, err
	}
	defer rows.Close()

	var trialPeriods []models.TrialPeriod
	for rows.Next() {
		var tp models.TrialPeriod
		var isTrial int

		err := rows.Scan(
			&tp.ID, &tp.CustomerName, &tp.Source, &tp.StartTime,
			&tp.EndTime, &isTrial, &tp.CreatedAt,
		)
		if err != nil {
			return nil, err
		}

		tp.IsTrial = isTrial == 1
		trialPeriods = append(trialPeriods, tp)
	}

	return trialPeriods, rows.Err()
}

func (ts *mysqlTrialPeriodStorage) GetTrialPeriodByID(id string) (*models.TrialPeriod, error) {
	query := `
		SELECT id, customer_name, COALESCE(source, '') as source, start_time, end_time, is_trial, created_at
		FROM trial_periods 
		WHERE id = ?
	`

	var tp models.TrialPeriod
	var isTrial int

	err := ts.db.QueryRow(query, id).Scan(
		&tp.ID, &tp.CustomerName, &tp.Source, &tp.StartTime,
		&tp.EndTime, &isTrial, &tp.CreatedAt,
	)

	if err == sql.ErrNoRows {
		return nil, nil
	}
	if err != nil {
		return nil, err
	}

	tp.IsTrial = isTrial == 1
	return &tp, nil
}

func (ts *mysqlTrialPeriodStorage) CreateTrialPeriod(trialPeriod models.TrialPeriod) (*models.TrialPeriod, error) {
	if trialPeriod.ID == "" {
		trialPeriod.ID = generateTrialPeriodMySQLUUID()
	}
	if trialPeriod.CreatedAt.IsZero() {
		trialPeriod.CreatedAt = time.Now()
	}

	query := `
		INSERT INTO trial_periods (id, customer_name, source, start_time, end_time, is_trial, created_at)
		VALUES (?, ?, ?, ?, ?, ?, ?)
	`

	isTrial := 0
	if trialPeriod.IsTrial {
		isTrial = 1
	}

	_, err := ts.db.Exec(query,
		trialPeriod.ID, trialPeriod.CustomerName, trialPeriod.Source, trialPeriod.StartTime,
		trialPeriod.EndTime, isTrial, trialPeriod.CreatedAt,
	)

	if err != nil {
		return nil, err
	}

	return &trialPeriod, nil
}

func (ts *mysqlTrialPeriodStorage) UpdateTrialPeriod(id string, updates models.UpdateTrialPeriodRequest) error {
	// 首先获取现有记录
	existing, err := ts.GetTrialPeriodByID(id)
	if err != nil || existing == nil {
		return err
	}

	// 应用更新
	if updates.CustomerName != nil {
		existing.CustomerName = *updates.CustomerName
	}
	if updates.Source != nil {
		existing.Source = *updates.Source
	}
	if updates.StartTime != nil {
		startTime, err := time.Parse(time.RFC3339, *updates.StartTime)
		if err == nil {
			existing.StartTime = startTime
		}
	}
	if updates.EndTime != nil {
		endTime, err := time.Parse(time.RFC3339, *updates.EndTime)
		if err == nil {
			existing.EndTime = endTime
		}
	}
	if updates.IsTrial != nil {
		existing.IsTrial = *updates.IsTrial
	}

	query := `
		UPDATE trial_periods 
		SET customer_name = ?, source = ?, start_time = ?, end_time = ?, is_trial = ?
		WHERE id = ?
	`

	isTrial := 0
	if existing.IsTrial {
		isTrial = 1
	}

	_, err = ts.db.Exec(query,
		existing.CustomerName, existing.Source, existing.StartTime, existing.EndTime,
		isTrial, id,
	)

	return err
}

func (ts *mysqlTrialPeriodStorage) DeleteTrialPeriod(id string) error {
	query := `DELETE FROM trial_periods WHERE id = ?`
	_, err := ts.db.Exec(query, id)
	if err != nil {
		// 检查是否是权限不足错误
		if strings.Contains(err.Error(), "command denied") || strings.Contains(err.Error(), "DELETE command denied") {
			return fmt.Errorf("数据库权限不足：无法执行删除操作，请联系管理员")
		}
		return err
	}
	return nil
}

func generateTrialPeriodMySQLUUID() string {
	bytes := make([]byte, 16)
	rand.Read(bytes)
	bytes[6] = (bytes[6] & 0x0f) | 0x40 // Version 4
	bytes[8] = (bytes[8] & 0x3f) | 0x80 // Variant
	return hex.EncodeToString(bytes)
}
