package service

import (
	"errors"
	"time"
	"web-qudo-be/app/database/entity"
	approvalWorkflowStepsRepo "web-qudo-be/app/module/approval_workflow_steps/repository"
	approvalWorkflowsRepo "web-qudo-be/app/module/approval_workflows/repository"
	"web-qudo-be/app/module/article_approval_flows/repository"
	"web-qudo-be/app/module/article_approval_flows/request"
	approvalStepLogsRepo "web-qudo-be/app/module/article_approval_step_logs/repository"
	articlesRepo "web-qudo-be/app/module/articles/repository"
	usersRepo "web-qudo-be/app/module/users/repository"
	"web-qudo-be/utils/paginator"

	"github.com/google/uuid"
	"github.com/rs/zerolog"
)

type articleApprovalFlowsService struct {
	ArticleApprovalFlowsRepository    repository.ArticleApprovalFlowsRepository
	ApprovalWorkflowsRepository       approvalWorkflowsRepo.ApprovalWorkflowsRepository
	ApprovalWorkflowStepsRepository   approvalWorkflowStepsRepo.ApprovalWorkflowStepsRepository
	ArticleApprovalStepLogsRepository approvalStepLogsRepo.ArticleApprovalStepLogsRepository
	ArticlesRepository                articlesRepo.ArticlesRepository
	UsersRepository                   usersRepo.UsersRepository
	Log                               zerolog.Logger
}

// ArticleApprovalFlowsService define interface of IArticleApprovalFlowsService
type ArticleApprovalFlowsService interface {
	// Basic CRUD
	GetAll(clientId *uuid.UUID, req request.ArticleApprovalFlowsQueryRequest) (flows []*entity.ArticleApprovalFlows, paging paginator.Pagination, err error)
	FindOne(clientId *uuid.UUID, id uint) (flow *entity.ArticleApprovalFlows, err error)
	Create(clientId *uuid.UUID, flow *entity.ArticleApprovalFlows) (flowReturn *entity.ArticleApprovalFlows, err error)
	Update(id uint, flow *entity.ArticleApprovalFlows) (err error)
	Delete(clientId *uuid.UUID, id uint) (err error)

	// Article submission and approval workflow
	SubmitArticleForApproval(clientId *uuid.UUID, articleId uint, submittedById uint, workflowId *uint) (flow *entity.ArticleApprovalFlows, err error)
	ApproveStep(clientId *uuid.UUID, flowId uint, approvedById uint, message string) (err error)
	RejectArticle(clientId *uuid.UUID, flowId uint, rejectedById uint, reason string) (err error)
	RequestRevision(clientId *uuid.UUID, flowId uint, requestedById uint, revisionMessage string) (err error)
	ResubmitAfterRevision(clientId *uuid.UUID, flowId uint, resubmittedById uint) (err error)

	// Dashboard and queue methods
	GetPendingApprovals(clientId *uuid.UUID, userLevelId uint, page, limit int, filters map[string]interface{}) (flows []*entity.ArticleApprovalFlows, paging paginator.Pagination, err error)
	GetMyApprovalQueue(clientId *uuid.UUID, userLevelId uint, page, limit int, includePreview bool, urgentOnly bool) (flows []*entity.ArticleApprovalFlows, paging paginator.Pagination, err error)
	GetApprovalHistory(clientId *uuid.UUID, articleId uint, page, limit int) (logs []*entity.ArticleApprovalStepLogs, paging paginator.Pagination, err error)

	// Statistics and analytics
	GetPendingCountByLevel(clientId *uuid.UUID, userLevelId uint) (count int64, err error)
	GetOverdueCountByLevel(clientId *uuid.UUID, userLevelId uint) (count int64, err error)
	GetApprovalStatistics(clientId *uuid.UUID, userLevelId uint, startDate, endDate time.Time) (stats map[string]interface{}, err error)
	GetWorkloadAnalytics(clientId *uuid.UUID, userLevelId uint) (analytics map[string]interface{}, err error)

	// Workflow management
	CanUserApproveStep(clientId *uuid.UUID, flowId uint, userId uint, userLevelId uint) (canApprove bool, reason string, err error)
	GetCurrentStepInfo(clientId *uuid.UUID, flowId uint) (stepInfo map[string]interface{}, err error)
	GetNextStepPreview(clientId *uuid.UUID, flowId uint) (nextStep *entity.ApprovalWorkflowSteps, err error)
}

func NewArticleApprovalFlowsService(
	articleApprovalFlowsRepository repository.ArticleApprovalFlowsRepository,
	approvalWorkflowsRepository approvalWorkflowsRepo.ApprovalWorkflowsRepository,
	approvalWorkflowStepsRepository approvalWorkflowStepsRepo.ApprovalWorkflowStepsRepository,
	articleApprovalStepLogsRepository approvalStepLogsRepo.ArticleApprovalStepLogsRepository,
	articlesRepository articlesRepo.ArticlesRepository,
	usersRepository usersRepo.UsersRepository,
	log zerolog.Logger,
) ArticleApprovalFlowsService {
	return &articleApprovalFlowsService{
		ArticleApprovalFlowsRepository:    articleApprovalFlowsRepository,
		ApprovalWorkflowsRepository:       approvalWorkflowsRepository,
		ApprovalWorkflowStepsRepository:   approvalWorkflowStepsRepository,
		ArticleApprovalStepLogsRepository: articleApprovalStepLogsRepository,
		ArticlesRepository:                articlesRepository,
		UsersRepository:                   usersRepository,
		Log:                               log,
	}
}

// Basic CRUD implementations
func (_i *articleApprovalFlowsService) GetAll(clientId *uuid.UUID, req request.ArticleApprovalFlowsQueryRequest) (flows []*entity.ArticleApprovalFlows, paging paginator.Pagination, err error) {
	return _i.ArticleApprovalFlowsRepository.GetAll(clientId, req)
}
func (_i *articleApprovalFlowsService) FindOne(clientId *uuid.UUID, id uint) (flow *entity.ArticleApprovalFlows, err error) {
	return _i.ArticleApprovalFlowsRepository.FindOne(clientId, id)
}

func (_i *articleApprovalFlowsService) Create(clientId *uuid.UUID, flow *entity.ArticleApprovalFlows) (flowReturn *entity.ArticleApprovalFlows, err error) {
	return _i.ArticleApprovalFlowsRepository.Create(clientId, flow)
}

func (_i *articleApprovalFlowsService) Update(id uint, flow *entity.ArticleApprovalFlows) (err error) {
	return _i.ArticleApprovalFlowsRepository.Update(id, flow)
}

func (_i *articleApprovalFlowsService) Delete(clientId *uuid.UUID, id uint) (err error) {
	return _i.ArticleApprovalFlowsRepository.Delete(clientId, id)
}

// Article submission and approval workflow
func (_i *articleApprovalFlowsService) SubmitArticleForApproval(clientId *uuid.UUID, articleId uint, submittedById uint, workflowId *uint) (flow *entity.ArticleApprovalFlows, err error) {
	// Check if article already has an active approval flow
	existingFlow, err := _i.ArticleApprovalFlowsRepository.FindActiveByArticleId(articleId)
	if err == nil && existingFlow != nil {
		return nil, errors.New("article already has an active approval flow")
	}

	// Get workflow (use default if not specified)
	var workflow *entity.ApprovalWorkflows
	if workflowId != nil {
		workflow, err = _i.ApprovalWorkflowsRepository.FindOne(clientId, *workflowId)
	} else {
		workflow, err = _i.ApprovalWorkflowsRepository.FindDefault(clientId)
	}

	if err != nil {
		return nil, err
	}

	if workflow == nil {
		return nil, errors.New("no workflow found")
	}

	if workflow.IsActive != nil && !*workflow.IsActive {
		return nil, errors.New("workflow is not active")
	}

	// Get first step of workflow
	firstStep, err := _i.ApprovalWorkflowStepsRepository.FindByWorkflowAndStep(clientId, workflow.ID, 1)
	if err != nil {
		return nil, err
	}

	if firstStep == nil {
		return nil, errors.New("workflow has no steps")
	}

	// Create approval flow
	flow = &entity.ArticleApprovalFlows{
		ArticleId:     articleId,
		WorkflowId:    workflow.ID,
		CurrentStep:   1,
		StatusId:      1, // pending
		SubmittedById: submittedById,
		SubmittedAt:   time.Now(),
	}

	flow, err = _i.ArticleApprovalFlowsRepository.Create(clientId, flow)
	if err != nil {
		return nil, err
	}

	// Get current article data first
	currentArticle, err := _i.ArticlesRepository.FindOne(clientId, articleId)
	if err != nil {
		return nil, err
	}

	// Update only the necessary fields
	currentArticle.WorkflowId = &workflow.ID
	currentArticle.CurrentApprovalStep = &flow.CurrentStep
	currentArticle.StatusId = &[]int{1}[0] // pending approval

	err = _i.ArticlesRepository.UpdateSkipNull(clientId, articleId, currentArticle)
	if err != nil {
		return nil, err
	}

	// Process auto-skip logic based on user level
	err = _i.processAutoSkipSteps(clientId, flow, submittedById)
	if err != nil {
		return nil, err
	}

	return flow, nil
}

// processAutoSkipSteps handles automatic step skipping based on user level
func (_i *articleApprovalFlowsService) processAutoSkipSteps(clientId *uuid.UUID, flow *entity.ArticleApprovalFlows, submittedById uint) error {
	// Get user level of the submitter
	userLevelId, err := _i.getUserLevelId(clientId, submittedById)
	if err != nil {
		return err
	}

	// Get all workflow steps
	steps, err := _i.ApprovalWorkflowStepsRepository.GetByWorkflowId(clientId, flow.WorkflowId)
	if err != nil {
		return err
	}

	// Sort steps by step order
	sortStepsByOrder(steps)

	// Process each step to determine if it should be auto-skipped
	for _, step := range steps {
		shouldSkip := _i.shouldSkipStep(userLevelId, step.RequiredUserLevelId)

		if shouldSkip {
			// Create skip log
			stepLog := &entity.ArticleApprovalStepLogs{
				ApprovalFlowId: flow.ID,
				StepOrder:      step.StepOrder,
				StepName:       step.StepName,
				ApprovedById:   &submittedById,
				Action:         "auto_skip",
				Message:        &[]string{"Step auto-skipped due to user level"}[0],
				ProcessedAt:    time.Now(),
				UserLevelId:    step.RequiredUserLevelId,
			}

			_, err = _i.ArticleApprovalStepLogsRepository.Create(clientId, stepLog)
			if err != nil {
				return err
			}

			// Update flow to next step (handle step order starting from 0)
			nextStepOrder := step.StepOrder + 1
			flow.CurrentStep = nextStepOrder
		} else {
			// Stop at first step that cannot be skipped
			break
		}
	}

	// Update flow with final current step
	err = _i.ArticleApprovalFlowsRepository.Update(flow.ID, flow)
	if err != nil {
		return err
	}

	// Get current article data first
	currentArticle, err := _i.ArticlesRepository.FindOne(clientId, flow.ArticleId)
	if err != nil {
		return err
	}

	// Update only the necessary fields
	currentArticle.CurrentApprovalStep = &flow.CurrentStep

	err = _i.ArticlesRepository.UpdateSkipNull(clientId, flow.ArticleId, currentArticle)
	if err != nil {
		return err
	}

	// Check if all steps were skipped (workflow complete)
	// Find the highest step order
	maxStepOrder := 0
	for _, step := range steps {
		if step.StepOrder > maxStepOrder {
			maxStepOrder = step.StepOrder
		}
	}

	if flow.CurrentStep > maxStepOrder {
		// All steps completed, mark as approved
		flow.StatusId = 2    // approved
		flow.CurrentStep = 0 // Set to 0 to indicate completion
		flow.CompletedAt = &[]time.Time{time.Now()}[0]

		err = _i.ArticleApprovalFlowsRepository.Update(flow.ID, flow)
		if err != nil {
			return err
		}

		// Get current article data first
		currentArticle, err := _i.ArticlesRepository.FindOne(clientId, flow.ArticleId)
		if err != nil {
			return err
		}

		// Update only the necessary fields
		currentArticle.StatusId = &[]int{2}[0]            // approved
		currentArticle.CurrentApprovalStep = &[]int{0}[0] // Set to 0 to indicate completion

		err = _i.ArticlesRepository.UpdateSkipNull(clientId, flow.ArticleId, currentArticle)
		if err != nil {
			return err
		}
	}

	return nil
}

// getUserLevelId gets the user level ID for a given user
func (_i *articleApprovalFlowsService) getUserLevelId(clientId *uuid.UUID, userId uint) (uint, error) {
	// Get user from database to retrieve user level
	user, err := _i.UsersRepository.FindOne(clientId, userId)
	if err != nil {
		_i.Log.Error().Err(err).Uint("userId", userId).Msg("Failed to find user")
		return 0, err
	}

	if user.UserLevel == nil {
		_i.Log.Error().Uint("userId", userId).Msg("User has no user level")
		return 0, errors.New("user has no user level")
	}

	_i.Log.Info().
		Uint("userId", userId).
		Uint("userLevelId", user.UserLevel.ID).
		Str("userLevelName", user.UserLevel.Name).
		Msg("Retrieved user level from database")

	return user.UserLevel.ID, nil
}

// shouldSkipStep determines if a step should be auto-skipped based on user level
func (_i *articleApprovalFlowsService) shouldSkipStep(userLevelId, requiredLevelId uint) bool {
	// Get user level details to compare level numbers
	// User level with lower level_number (higher authority) can skip steps requiring higher level_number
	// For now, we'll use a simple comparison based on IDs
	// In production, this should compare level_number fields

	// Simple logic: if user level ID is less than required level ID, they can skip
	// This assumes level 1 (ID=1) has higher authority than level 2 (ID=2), etc.
	return userLevelId < requiredLevelId
}

// sortStepsByOrder sorts workflow steps by their step order
func sortStepsByOrder(steps []*entity.ApprovalWorkflowSteps) {
	// Simple bubble sort for step order
	n := len(steps)
	for i := 0; i < n-1; i++ {
		for j := 0; j < n-i-1; j++ {
			if steps[j].StepOrder > steps[j+1].StepOrder {
				steps[j], steps[j+1] = steps[j+1], steps[j]
			}
		}
	}
}

func (_i *articleApprovalFlowsService) ApproveStep(clientId *uuid.UUID, flowId uint, approvedById uint, message string) (err error) {
	// Get approval flow
	flow, err := _i.ArticleApprovalFlowsRepository.FindOne(clientId, flowId)
	if err != nil {
		return err
	}

	if flow == nil {
		return errors.New("approval flow not found")
	}

	if flow.StatusId != 1 && flow.StatusId != 4 { // not pending or revision_requested
		return errors.New("approval flow is not in pending state")
	}

	// Get current step
	currentStep, err := _i.ApprovalWorkflowStepsRepository.FindByWorkflowAndStep(clientId, flow.WorkflowId, flow.CurrentStep)
	if err != nil {
		return err
	}

	if currentStep == nil {
		return errors.New("current step not found")
	}

	// Create step log
	stepLog := &entity.ArticleApprovalStepLogs{
		ApprovalFlowId: flow.ID,
		StepOrder:      flow.CurrentStep,
		StepName:       currentStep.StepName,
		ApprovedById:   &approvedById,
		Action:         "approve",
		Message:        &message,
		ProcessedAt:    time.Now(),
		UserLevelId:    currentStep.RequiredUserLevelId,
	}

	_, err = _i.ArticleApprovalStepLogsRepository.Create(clientId, stepLog)
	if err != nil {
		return err
	}

	// Check if there's a next step
	nextStep, err := _i.ApprovalWorkflowStepsRepository.GetNextStep(clientId, flow.WorkflowId, flow.CurrentStep)
	if err != nil && err.Error() != "record not found" {
		return err
	}

	if nextStep == nil || nextStep.ID == 0 {
		// No next step - approval complete
		flowUpdate := &entity.ArticleApprovalFlows{
			StatusId:    2, // approved
			CurrentStep: 0, // Set to 0 to indicate completion
			CompletedAt: &[]time.Time{time.Now()}[0],
		}

		// Debug logging
		_i.Log.Info().
			Interface("flowUpdate :: ", flowUpdate).
			Msg("Retrieved next step from database")

		err = _i.ArticleApprovalFlowsRepository.Update(flowId, flowUpdate)
		if err != nil {
			return err
		}

		// Get current article data first
		currentArticle, err := _i.ArticlesRepository.FindOne(clientId, flow.ArticleId)
		if err != nil {
			return err
		}

		// Update only the necessary fields
		currentArticle.StatusId = &[]int{2}[0]            // approved
		currentArticle.CurrentApprovalStep = &[]int{0}[0] // Set to 0 to indicate completion
		currentArticle.IsPublish = &[]bool{true}[0]       // Set to true to indicate publication
		currentArticle.IsDraft = &[]bool{false}[0]        // Set to false to indicate publication

		err = _i.ArticlesRepository.UpdateSkipNull(clientId, flow.ArticleId, currentArticle)
		if err != nil {
			return err
		}
	} else {
		// Move to next step
		flowUpdate := &entity.ArticleApprovalFlows{
			CurrentStep: nextStep.StepOrder,
			StatusId:    1, // pending
		}

		err = _i.ArticleApprovalFlowsRepository.Update(flowId, flowUpdate)
		if err != nil {
			return err
		}

		// Get current article data first
		currentArticle, err := _i.ArticlesRepository.FindOne(clientId, flow.ArticleId)
		if err != nil {
			return err
		}

		// Update only the necessary fields
		currentArticle.CurrentApprovalStep = &nextStep.StepOrder

		err = _i.ArticlesRepository.UpdateSkipNull(clientId, flow.ArticleId, currentArticle)
		if err != nil {
			return err
		}
	}

	return nil
}

func (_i *articleApprovalFlowsService) RejectArticle(clientId *uuid.UUID, flowId uint, rejectedById uint, reason string) (err error) {
	// Get approval flow
	flow, err := _i.ArticleApprovalFlowsRepository.FindOne(clientId, flowId)
	if err != nil {
		return err
	}

	if flow == nil {
		return errors.New("approval flow not found")
	}

	if flow.StatusId != 1 && flow.StatusId != 4 { // not pending or revision_requested
		return errors.New("approval flow is not in pending state")
	}

	// Get current step
	currentStep, err := _i.ApprovalWorkflowStepsRepository.FindByWorkflowAndStep(clientId, flow.WorkflowId, flow.CurrentStep)
	if err != nil {
		return err
	}

	// Create step log
	stepLog := &entity.ArticleApprovalStepLogs{
		ApprovalFlowId: flow.ID,
		StepOrder:      flow.CurrentStep,
		StepName:       currentStep.StepName,
		ApprovedById:   &rejectedById,
		Action:         "reject",
		Message:        &reason,
		ProcessedAt:    time.Now(),
		UserLevelId:    currentStep.RequiredUserLevelId,
	}

	_, err = _i.ArticleApprovalStepLogsRepository.Create(clientId, stepLog)
	if err != nil {
		return err
	}

	// Update approval flow status
	flowUpdate := &entity.ArticleApprovalFlows{
		StatusId:        3, // rejected
		RejectionReason: &reason,
		CompletedAt:     &[]time.Time{time.Now()}[0],
	}

	err = _i.ArticleApprovalFlowsRepository.Update(flowId, flowUpdate)
	if err != nil {
		return err
	}

	// Get current article data first
	currentArticle, err := _i.ArticlesRepository.FindOne(clientId, flow.ArticleId)
	if err != nil {
		return err
	}

	// Update only the necessary fields
	currentArticle.StatusId = &[]int{3}[0] // rejected
	currentArticle.CurrentApprovalStep = nil

	err = _i.ArticlesRepository.UpdateSkipNull(clientId, flow.ArticleId, currentArticle)
	if err != nil {
		return err
	}

	return nil
}

func (_i *articleApprovalFlowsService) RequestRevision(clientId *uuid.UUID, flowId uint, requestedById uint, revisionMessage string) (err error) {
	// Get approval flow
	flow, err := _i.ArticleApprovalFlowsRepository.FindOne(clientId, flowId)
	if err != nil {
		return err
	}

	if flow == nil {
		return errors.New("approval flow not found")
	}

	if flow.StatusId != 1 { // not pending
		return errors.New("approval flow is not in pending state")
	}

	// Get current step
	currentStep, err := _i.ApprovalWorkflowStepsRepository.FindByWorkflowAndStep(clientId, flow.WorkflowId, flow.CurrentStep)
	if err != nil {
		return err
	}

	// Create step log
	stepLog := &entity.ArticleApprovalStepLogs{
		ApprovalFlowId: flow.ID,
		StepOrder:      flow.CurrentStep,
		StepName:       currentStep.StepName,
		ApprovedById:   &requestedById,
		Action:         "request_revision",
		Message:        &revisionMessage,
		ProcessedAt:    time.Now(),
		UserLevelId:    currentStep.RequiredUserLevelId,
	}

	_, err = _i.ArticleApprovalStepLogsRepository.Create(clientId, stepLog)
	if err != nil {
		return err
	}

	// Update approval flow status
	flowUpdate := &entity.ArticleApprovalFlows{
		StatusId:          4, // revision_requested
		RevisionRequested: &[]bool{true}[0],
		RevisionMessage:   &revisionMessage,
	}

	err = _i.ArticleApprovalFlowsRepository.Update(flowId, flowUpdate)
	if err != nil {
		return err
	}

	// Get current article data first
	currentArticle, err := _i.ArticlesRepository.FindOne(clientId, flow.ArticleId)
	if err != nil {
		return err
	}

	// Update only the necessary fields
	currentArticle.StatusId = &[]int{4}[0] // revision_requested

	err = _i.ArticlesRepository.UpdateSkipNull(clientId, flow.ArticleId, currentArticle)
	if err != nil {
		return err
	}

	return nil
}

func (_i *articleApprovalFlowsService) ResubmitAfterRevision(clientId *uuid.UUID, flowId uint, resubmittedById uint) (err error) {
	// Get approval flow
	flow, err := _i.ArticleApprovalFlowsRepository.FindOne(clientId, flowId)
	if err != nil {
		return err
	}

	if flow == nil {
		return errors.New("approval flow not found")
	}

	if flow.StatusId != 4 { // not revision_requested
		return errors.New("approval flow is not in revision requested state")
	}

	// Reset approval flow to pending
	flowUpdate := &entity.ArticleApprovalFlows{
		StatusId:          1, // pending
		RevisionRequested: &[]bool{false}[0],
		RevisionMessage:   nil,
		CurrentStep:       1, // restart from first step
	}

	err = _i.ArticleApprovalFlowsRepository.Update(flowId, flowUpdate)
	if err != nil {
		return err
	}

	// Get current article data first
	currentArticle, err := _i.ArticlesRepository.FindOne(clientId, flow.ArticleId)
	if err != nil {
		return err
	}

	// Update only the necessary fields
	currentArticle.StatusId = &[]int{1}[0] // pending approval
	currentArticle.CurrentApprovalStep = &[]int{1}[0]

	err = _i.ArticlesRepository.UpdateSkipNull(clientId, flow.ArticleId, currentArticle)
	if err != nil {
		return err
	}

	// Create resubmission log
	stepLog := &entity.ArticleApprovalStepLogs{
		ApprovalFlowId: flow.ID,
		StepOrder:      1,
		StepName:       "Resubmission",
		ApprovedById:   &resubmittedById,
		Action:         "resubmit",
		Message:        &[]string{"Article resubmitted after revision"}[0],
		ProcessedAt:    time.Now(),
	}

	_, err = _i.ArticleApprovalStepLogsRepository.Create(clientId, stepLog)
	if err != nil {
		return err
	}

	return nil
}

// Dashboard and queue methods
func (_i *articleApprovalFlowsService) GetPendingApprovals(clientId *uuid.UUID, userLevelId uint, page, limit int, filters map[string]interface{}) (flows []*entity.ArticleApprovalFlows, paging paginator.Pagination, err error) {
	return _i.ArticleApprovalFlowsRepository.GetPendingApprovals(clientId, userLevelId, page, limit, filters)
}

func (_i *articleApprovalFlowsService) GetMyApprovalQueue(clientId *uuid.UUID, userLevelId uint, page, limit int, includePreview bool, urgentOnly bool) (flows []*entity.ArticleApprovalFlows, paging paginator.Pagination, err error) {
	return _i.ArticleApprovalFlowsRepository.GetMyApprovalQueue(clientId, userLevelId, page, limit, includePreview, urgentOnly)
}

func (_i *articleApprovalFlowsService) GetApprovalHistory(clientId *uuid.UUID, articleId uint, page, limit int) (logs []*entity.ArticleApprovalStepLogs, paging paginator.Pagination, err error) {
	return _i.ArticleApprovalStepLogsRepository.GetApprovalHistory(clientId, articleId, page, limit)
}

// Statistics and analytics
func (_i *articleApprovalFlowsService) GetPendingCountByLevel(clientId *uuid.UUID, userLevelId uint) (count int64, err error) {
	return _i.ArticleApprovalFlowsRepository.GetPendingCountByLevel(clientId, userLevelId)
}

func (_i *articleApprovalFlowsService) GetOverdueCountByLevel(clientId *uuid.UUID, userLevelId uint) (count int64, err error) {
	return _i.ArticleApprovalFlowsRepository.GetOverdueCountByLevel(clientId, userLevelId)
}

func (_i *articleApprovalFlowsService) GetApprovalStatistics(clientId *uuid.UUID, userLevelId uint, startDate, endDate time.Time) (stats map[string]interface{}, err error) {
	stats = make(map[string]interface{})

	// Get approved count
	approvedCount, err := _i.ArticleApprovalFlowsRepository.GetApprovedCountByPeriod(clientId, userLevelId, startDate, endDate)
	if err != nil {
		return nil, err
	}

	// Get rejected count
	rejectedCount, err := _i.ArticleApprovalFlowsRepository.GetRejectedCountByPeriod(clientId, userLevelId, startDate, endDate)
	if err != nil {
		return nil, err
	}

	// Get revision request count
	revisionCount, err := _i.ArticleApprovalFlowsRepository.GetRevisionRequestCountByPeriod(clientId, userLevelId, startDate, endDate)
	if err != nil {
		return nil, err
	}

	stats["approved_count"] = approvedCount
	stats["rejected_count"] = rejectedCount
	stats["revision_requested_count"] = revisionCount
	stats["total_processed"] = approvedCount + rejectedCount + revisionCount
	stats["period_start"] = startDate
	stats["period_end"] = endDate

	return stats, nil
}

func (_i *articleApprovalFlowsService) GetWorkloadAnalytics(clientId *uuid.UUID, userLevelId uint) (analytics map[string]interface{}, err error) {
	return _i.ArticleApprovalFlowsRepository.GetLevelWorkload(clientId, userLevelId)
}

// Workflow management
func (_i *articleApprovalFlowsService) CanUserApproveStep(clientId *uuid.UUID, flowId uint, userId uint, userLevelId uint) (canApprove bool, reason string, err error) {
	// Get approval flow
	flow, err := _i.ArticleApprovalFlowsRepository.FindOne(clientId, flowId)
	if err != nil {
		return false, "", err
	}

	if flow == nil {
		return false, "approval flow not found", nil
	}

	if flow.StatusId != 1 && flow.StatusId != 4 { // not pending or revision_requested
		return false, "approval flow is not in pending state", nil
	}

	// Get current step
	currentStep, err := _i.ApprovalWorkflowStepsRepository.FindByWorkflowAndStep(clientId, flow.WorkflowId, flow.CurrentStep)
	if err != nil {
		return false, "", err
	}

	if currentStep == nil {
		return false, "current step not found", nil
	}

	// Check if user level matches required level
	if currentStep.RequiredUserLevelId != userLevelId {
		return false, "user level does not match required level for this step", nil
	}

	// Check if user submitted the article (cannot approve own submission)
	if flow.SubmittedById == userId {
		return false, "cannot approve own submission", nil
	}

	return true, "", nil
}

func (_i *articleApprovalFlowsService) GetCurrentStepInfo(clientId *uuid.UUID, flowId uint) (stepInfo map[string]interface{}, err error) {
	stepInfo = make(map[string]interface{})

	// Get approval flow
	flow, err := _i.ArticleApprovalFlowsRepository.FindOne(clientId, flowId)
	if err != nil {
		return nil, err
	}

	if flow == nil {
		return nil, errors.New("approval flow not found")
	}

	// Get current step
	currentStep, err := _i.ApprovalWorkflowStepsRepository.FindByWorkflowAndStep(clientId, flow.WorkflowId, flow.CurrentStep)
	if err != nil {
		return nil, err
	}

	stepInfo["current_step"] = flow.CurrentStep
	stepInfo["step_name"] = currentStep.StepName
	stepInfo["required_user_level_id"] = currentStep.RequiredUserLevelId
	stepInfo["can_skip"] = currentStep.CanSkip
	stepInfo["auto_approve_after_hours"] = currentStep.AutoApproveAfterHours
	stepInfo["status"] = flow.StatusId

	return stepInfo, nil
}

func (_i *articleApprovalFlowsService) GetNextStepPreview(clientId *uuid.UUID, flowId uint) (nextStep *entity.ApprovalWorkflowSteps, err error) {
	// Get approval flow
	flow, err := _i.ArticleApprovalFlowsRepository.FindOne(clientId, flowId)
	if err != nil {
		return nil, err
	}

	if flow == nil {
		return nil, errors.New("approval flow not found")
	}

	// Get next step
	nextStep, err = _i.ApprovalWorkflowStepsRepository.GetNextStep(clientId, flow.WorkflowId, flow.CurrentStep)
	if err != nil {
		return nil, err
	}

	return nextStep, nil
}
