package service

import (
	"context"
	"fmt"
	"time"
)

// ProjectLifecycleUpdater 项目生命周期状态更新接口
// 由 rmdc-core 注入，工单模块状态变更时调用
type ProjectLifecycleUpdater interface {
	UpdateLifecycleStatus(projectID, lifecycleStatus string) error
	SetLifecycleToDrafting(projectID string) error
	SetLifecycleToReviewing(projectID string) error
	SetLifecycleToReleased(projectID string) error
	SetLifecycleToModifying(projectID string) error
}

// ProjectLifecycleService 项目生命周期服务实现
type ProjectLifecycleService struct {
	repo        ProjectRepository
	versionSvc  *VersionService
	auditSvc    AuditService
	idempotency IdempotencyChecker
}

// NewProjectLifecycleService 创建项目生命周期服务
func NewProjectLifecycleService(
	repo ProjectRepository,
	versionSvc *VersionService,
	auditSvc AuditService,
) *ProjectLifecycleService {
	return &ProjectLifecycleService{
		repo:       repo,
		versionSvc: versionSvc,
		auditSvc:   auditSvc,
	}
}

// UpdateLifecycleStatus 更新项目生命周期状态
func (s *ProjectLifecycleService) UpdateLifecycleStatus(projectID, lifecycleStatus string) error {
	ctx := context.Background()

	// 幂等性检查
	idempotencyKey := fmt.Sprintf("lifecycle:%s:%s:%d", projectID, lifecycleStatus, time.Now().Unix()/60)
	if s.idempotency != nil && s.idempotency.Exists(idempotencyKey) {
		return nil // 已处理，直接返回
	}

	// 更新生命周期状态
	err := s.repo.UpdateLifecycleStatus(ctx, projectID, lifecycleStatus)
	if err != nil {
		return fmt.Errorf("update lifecycle status failed: %w", err)
	}

	// 记录审计日志
	s.auditSvc.Log(ctx, AuditLog{
		Resource:   "project",
		Action:     "lifecycle_change",
		ResourceID: projectID,
		Details: map[string]interface{}{
			"new_status": lifecycleStatus,
		},
	})

	// 标记已处理
	if s.idempotency != nil {
		s.idempotency.Set(idempotencyKey, 24*time.Hour)
	}

	return nil
}

// SetLifecycleToReleased 设置为已发布状态（审批通过时）
func (s *ProjectLifecycleService) SetLifecycleToReleased(projectID string) error {
	ctx := context.Background()

	// 1. 获取项目信息
	project, err := s.repo.GetByProjectID(ctx, projectID)
	if err != nil {
		return fmt.Errorf("get project failed: %w", err)
	}

	// 2. 获取草稿快照
	draftVersion, err := s.repo.GetActiveDraft(ctx, projectID)
	if err != nil {
		return fmt.Errorf("get draft failed: %w", err)
	}

	// 3. 开启事务
	return s.repo.Transaction(ctx, func(txCtx context.Context) error {
		// 3.1 更新生命周期状态
		if err := s.repo.UpdateLifecycleStatus(txCtx, projectID, LifecycleReleased); err != nil {
			return err
		}

		// 3.2 更新认证状态为正式
		if err := s.repo.UpdateCertificationStatus(txCtx, projectID, CertificationOfficial); err != nil {
			return err
		}

		// 3.3 将草稿内容合并到主表
		if err := s.repo.MergeDraftToMaster(txCtx, projectID, draftVersion.SnapshotData); err != nil {
			return err
		}

		// 3.4 创建正式版本快照
		snapshot := &VersionSnapshot{}
		if err := parseSnapshot(draftVersion.SnapshotData, snapshot); err != nil {
			return err
		}

		if err := s.versionSvc.CreateOfficialVersion(
			txCtx,
			projectID,
			snapshot,
			draftVersion.CommitterID,
			draftVersion.CommitterName,
			"审批通过，发布正式版本",
		); err != nil {
			return err
		}

		// 3.5 删除草稿
		if err := s.repo.DeleteDraft(txCtx, projectID, draftVersion.UserID); err != nil {
			return err
		}

		return nil
	})
}

// SetLifecycleToDrafting 设置为填写中状态（工单被打回后）
func (s *ProjectLifecycleService) SetLifecycleToDrafting(projectID string) error {
	ctx := context.Background()

	err := s.repo.UpdateLifecycleStatus(ctx, projectID, LifecycleDrafting)
	if err != nil {
		return fmt.Errorf("set lifecycle to drafting failed: %w", err)
	}

	s.auditSvc.Log(ctx, AuditLog{
		Resource:   "project",
		Action:     "lifecycle_change",
		ResourceID: projectID,
		Details: map[string]interface{}{
			"new_status": LifecycleDrafting,
			"reason":     "workflow_returned",
		},
	})

	return nil
}

// SetLifecycleToReviewing 设置为审核中状态（提交审核时）
func (s *ProjectLifecycleService) SetLifecycleToReviewing(projectID string) error {
	ctx := context.Background()

	// 更新生命周期状态
	err := s.repo.UpdateLifecycleStatus(ctx, projectID, LifecycleReviewing)
	if err != nil {
		return fmt.Errorf("set lifecycle to reviewing failed: %w", err)
	}

	// 更新认证状态为待审核
	err = s.repo.UpdateCertificationStatus(ctx, projectID, CertificationPending)
	if err != nil {
		return fmt.Errorf("set certification to pending failed: %w", err)
	}

	s.auditSvc.Log(ctx, AuditLog{
		Resource:   "project",
		Action:     "lifecycle_change",
		ResourceID: projectID,
		Details: map[string]interface{}{
			"new_status": LifecycleReviewing,
		},
	})

	return nil
}

// SetLifecycleToModifying 设置为变更中状态（发起修改工单时）
func (s *ProjectLifecycleService) SetLifecycleToModifying(projectID string) error {
	ctx := context.Background()

	err := s.repo.UpdateLifecycleStatus(ctx, projectID, LifecycleModifying)
	if err != nil {
		return fmt.Errorf("set lifecycle to modifying failed: %w", err)
	}

	s.auditSvc.Log(ctx, AuditLog{
		Resource:   "project",
		Action:     "lifecycle_change",
		ResourceID: projectID,
		Details: map[string]interface{}{
			"new_status": LifecycleModifying,
		},
	})

	return nil
}

// CheckVersionConflict 检查版本冲突（乐观锁）
func (s *ProjectLifecycleService) CheckVersionConflict(
	ctx context.Context,
	projectID string,
	baseVersion int,
) error {
	currentVersion, err := s.repo.GetCurrentVersion(ctx, projectID)
	if err != nil {
		return fmt.Errorf("get current version failed: %w", err)
	}

	if currentVersion != baseVersion {
		return &VersionConflictError{
			ProjectID:      projectID,
			BaseVersion:    baseVersion,
			CurrentVersion: currentVersion,
		}
	}

	return nil
}

// VersionConflictError 版本冲突错误
type VersionConflictError struct {
	ProjectID      string
	BaseVersion    int
	CurrentVersion int
}

func (e *VersionConflictError) Error() string {
	return fmt.Sprintf(
		"version conflict: project %s base version %d, current version %d",
		e.ProjectID, e.BaseVersion, e.CurrentVersion,
	)
}

// 辅助类型和函数

type ProjectRepository interface {
	GetByProjectID(ctx context.Context, projectID string) (*Project, error)
	UpdateLifecycleStatus(ctx context.Context, projectID, status string) error
	UpdateCertificationStatus(ctx context.Context, projectID, status string) error
	GetActiveDraft(ctx context.Context, projectID string) (*ProjectVersion, error)
	MergeDraftToMaster(ctx context.Context, projectID string, data []byte) error
	DeleteDraft(ctx context.Context, projectID string, userID int64) error
	GetCurrentVersion(ctx context.Context, projectID string) (int, error)
	Transaction(ctx context.Context, fn func(ctx context.Context) error) error
}

type AuditService interface {
	Log(ctx context.Context, log AuditLog)
}

type AuditLog struct {
	Resource   string
	Action     string
	ResourceID string
	Details    map[string]interface{}
}

type IdempotencyChecker interface {
	Exists(key string) bool
	Set(key string, ttl time.Duration)
}

type Project struct {
	ID                  int64
	ProjectID           string
	LifecycleStatus     string
	CertificationStatus string
	CurrentVersion      int
}

func parseSnapshot(data []byte, snapshot *VersionSnapshot) error {
	// JSON 解析实现
	return nil
}
