package service

import (
	"context"
	"fmt"
	"time"

	"gorm.io/gorm"
)

// Workflow 工单实体
type Workflow struct {
	ID              string    `gorm:"primaryKey;size:64"`
	Version         int       `gorm:"not null;default:1"`
	ModuleCode      string    `gorm:"size:32;not null"`
	WorkflowType    string    `gorm:"size:32;not null"`
	Priority        int       `gorm:"default:3"`
	Status          string    `gorm:"size:32;not null"`
	CurrentStep     int       `gorm:"default:1"`
	TotalSteps      int       `gorm:"default:1"`
	CreatorID       int64     `gorm:"not null"`
	CreatorName     string    `gorm:"size:64"`
	AssigneeID      *int64
	AssigneeName    string    `gorm:"size:64"`
	DelegatedBy     *int64
	Deadline        *time.Time
	StartedAt       *time.Time
	CompletedAt     *time.Time
	Title           string `gorm:"size:256"`
	Description     string `gorm:"type:text"`
	BusinessPayload string `gorm:"type:json"`
	ResultPayload   string `gorm:"type:json"`
	CreatedAt       time.Time
	UpdatedAt       time.Time
}

// WorkflowTrackHistory 工单追踪历史
type WorkflowTrackHistory struct {
	ID            int64  `gorm:"primaryKey;autoIncrement"`
	WorkflowID    string `gorm:"size:64;not null"`
	FromStatus    string `gorm:"size:32"`
	ToStatus      string `gorm:"size:32"`
	Event         string `gorm:"size:32"`
	OperatorID    int64
	OperatorType  string `gorm:"size:16"` // user / system / timer
	OperatorIP    string `gorm:"size:45"`
	ChangeDetails string `gorm:"type:json"`
	Remark        string `gorm:"type:text"`
	CreatedAt     time.Time
}

// CreateWorkflowRequest 创建工单请求
type CreateWorkflowRequest struct {
	ModuleCode      string
	ModulePrefix    string
	WorkflowType    string
	Title           string
	Description     string
	Priority        int
	CreatorID       int64
	CreatorName     string
	CreatorUsername string
	AssigneeID      *int64
	Deadline        *time.Time
	BusinessPayload string
}

// TransitionRequest 状态转换请求
type TransitionRequest struct {
	WorkflowID   string
	Version      int
	FromStatus   string
	ToStatus     string
	Event        string
	OperatorID   int64
	OperatorType string
	OperatorIP   string
	Remark       string
}

// 错误定义
var (
	ErrVersionConflict  = fmt.Errorf("version conflict")
	ErrWorkflowNotFound = fmt.Errorf("workflow not found")
	ErrInvalidTransition = fmt.Errorf("invalid state transition")
)

// WorkflowService 工单服务
type WorkflowService struct {
	db *gorm.DB
}

// NewWorkflowService 创建工单服务
func NewWorkflowService(db *gorm.DB) *WorkflowService {
	return &WorkflowService{db: db}
}

// CreateWorkflow 创建工单
func (s *WorkflowService) CreateWorkflow(ctx context.Context, req *CreateWorkflowRequest) (*Workflow, error) {
	// 生成工单ID: {module_prefix}-{timestamp}-{creator}
	workflowID := fmt.Sprintf("%s-%s-%s",
		req.ModulePrefix,
		time.Now().Format("20060102150405"),
		req.CreatorUsername,
	)

	workflow := &Workflow{
		ID:              workflowID,
		Version:         1,
		ModuleCode:      req.ModuleCode,
		WorkflowType:    req.WorkflowType,
		Status:          StatusCreated,
		Priority:        req.Priority,
		CreatorID:       req.CreatorID,
		CreatorName:     req.CreatorName,
		AssigneeID:      req.AssigneeID,
		Title:           req.Title,
		Description:     req.Description,
		Deadline:        req.Deadline,
		BusinessPayload: req.BusinessPayload,
		CreatedAt:       time.Now(),
		UpdatedAt:       time.Now(),
	}

	// 事务：同时创建主表和扩展表
	err := s.db.Transaction(func(tx *gorm.DB) error {
		if err := tx.Create(workflow).Error; err != nil {
			return err
		}
		// 根据工单类型创建扩展表记录
		return s.createExtension(tx, workflow, req)
	})

	if err != nil {
		return nil, err
	}

	return workflow, nil
}

// createExtension 根据工单类型创建扩展表记录
func (s *WorkflowService) createExtension(tx *gorm.DB, workflow *Workflow, req *CreateWorkflowRequest) error {
	switch workflow.WorkflowType {
	case WorkflowTypeUserRegistration:
		// 创建用户注册扩展记录
		return tx.Exec(`
			INSERT INTO user_registration_ext (workflow_id, target_user_id, original_status)
			VALUES (?, ?, ?)
		`, workflow.ID, 0, "disabled").Error
	case WorkflowTypeUserManagement:
		// 创建用户管理扩展记录
		return tx.Exec(`
			INSERT INTO user_management_ext (workflow_id, target_user_id, action_type)
			VALUES (?, ?, ?)
		`, workflow.ID, 0, "modify").Error
	case WorkflowTypeProjectDetail:
		// 创建项目详情扩展记录
		return tx.Exec(`
			INSERT INTO project_detail_ext (workflow_id, project_id)
			VALUES (?, ?)
		`, workflow.ID, "").Error
	case WorkflowTypeMicroserviceUpdate:
		// 创建微服务更新扩展记录
		return tx.Exec(`
			INSERT INTO microservice_update_ext (workflow_id, project_id, namespace, service_name)
			VALUES (?, ?, ?, ?)
		`, workflow.ID, "", "", "").Error
	}
	return nil
}

// TransitionWorkflow 状态转换（带乐观锁）
func (s *WorkflowService) TransitionWorkflow(ctx context.Context, req *TransitionRequest) error {
	// 验证状态转换是否合法
	toStatus, valid := CanTransition(State(req.FromStatus), Event(req.Event))
	if !valid {
		return ErrInvalidTransition
	}
	req.ToStatus = string(toStatus)

	return s.db.Transaction(func(tx *gorm.DB) error {
		// 1. 乐观锁更新
		result := tx.Model(&Workflow{}).
			Where("id = ? AND version = ?", req.WorkflowID, req.Version).
			Updates(map[string]interface{}{
				"status":     req.ToStatus,
				"version":    gorm.Expr("version + 1"),
				"updated_at": time.Now(),
			})

		if result.RowsAffected == 0 {
			return ErrVersionConflict // 409
		}

		// 2. 记录状态变更历史
		history := &WorkflowTrackHistory{
			WorkflowID:   req.WorkflowID,
			FromStatus:   req.FromStatus,
			ToStatus:     req.ToStatus,
			Event:        req.Event,
			OperatorID:   req.OperatorID,
			OperatorType: req.OperatorType,
			OperatorIP:   req.OperatorIP,
			Remark:       req.Remark,
			CreatedAt:    time.Now(),
		}
		return tx.Create(history).Error
	})
}

// GetWorkflow 获取工单详情
func (s *WorkflowService) GetWorkflow(ctx context.Context, workflowID string) (*Workflow, error) {
	var workflow Workflow
	if err := s.db.Where("id = ?", workflowID).First(&workflow).Error; err != nil {
		if err == gorm.ErrRecordNotFound {
			return nil, ErrWorkflowNotFound
		}
		return nil, err
	}
	return &workflow, nil
}

// GetWorkflowHistory 获取工单历史
func (s *WorkflowService) GetWorkflowHistory(ctx context.Context, workflowID string) ([]WorkflowTrackHistory, error) {
	var history []WorkflowTrackHistory
	err := s.db.Where("workflow_id = ?", workflowID).
		Order("created_at ASC").
		Find(&history).Error
	return history, err
}

// 工单类型常量
const (
	WorkflowTypeUserRegistration   = "user_registration"
	WorkflowTypeUserManagement     = "user_management"
	WorkflowTypeProjectDetail      = "project_detail"
	WorkflowTypeMicroserviceUpdate = "microservice_update"
)

// 状态常量
const (
	StatusCreated       = "created"
	StatusPending       = "pending"
	StatusAssigned      = "assigned"
	StatusInProgress    = "in_progress"
	StatusPendingReview = "pending_review"
	StatusReturned      = "returned"
	StatusApproved      = "approved"
	StatusRejected      = "rejected"
	StatusRevoked       = "revoked"
	StatusClosed        = "closed"
)
