package service

import (
	"encoding/json"
	"errors"
	"fmt"
	"netidhub-saas-be/app/database/entity"
	stepRepo "netidhub-saas-be/app/module/approval_workflow_steps/repository"
	"netidhub-saas-be/app/module/approval_workflows/repository"
	"netidhub-saas-be/app/module/approval_workflows/request"
	"netidhub-saas-be/app/module/approval_workflows/response"
	articleApprovalFlowsRepo "netidhub-saas-be/app/module/article_approval_flows/repository"
	articleCategoriesRepo "netidhub-saas-be/app/module/article_categories/repository"
	clientApprovalSettingsRepo "netidhub-saas-be/app/module/client_approval_settings/repository"
	userLevelsRepo "netidhub-saas-be/app/module/user_levels/repository"
	userLevelsReq "netidhub-saas-be/app/module/user_levels/request"
	userRolesRepo "netidhub-saas-be/app/module/user_roles/repository"
	usersRepo "netidhub-saas-be/app/module/users/repository"
	"netidhub-saas-be/utils/paginator"
	utilSvc "netidhub-saas-be/utils/service"

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

type approvalWorkflowsService struct {
	ApprovalWorkflowsRepository      repository.ApprovalWorkflowsRepository
	ApprovalWorkflowStepsRepository  stepRepo.ApprovalWorkflowStepsRepository
	ClientApprovalSettingsRepository clientApprovalSettingsRepo.ClientApprovalSettingsRepository
	UsersRepository                  usersRepo.UsersRepository
	UserLevelsRepository             userLevelsRepo.UserLevelsRepository
	UserRolesRepository              userRolesRepo.UserRolesRepository
	ArticleCategoriesRepository      articleCategoriesRepo.ArticleCategoriesRepository
	ArticleApprovalFlowsRepository   articleApprovalFlowsRepo.ArticleApprovalFlowsRepository
	Log                              zerolog.Logger
}

// ApprovalWorkflowsService define interface of IApprovalWorkflowsService
type ApprovalWorkflowsService interface {
	// Basic CRUD
	GetAll(authToken string, req request.ApprovalWorkflowsQueryRequest) (workflows []*entity.ApprovalWorkflows, paging paginator.Pagination, err error)
	FindOne(authToken string, id uint) (workflow *entity.ApprovalWorkflows, err error)
	Create(authToken string, workflow *entity.ApprovalWorkflows, steps []*entity.ApprovalWorkflowSteps) (workflowReturn *entity.ApprovalWorkflows, err error)
	Update(authToken string, id uint, workflow *entity.ApprovalWorkflows) (err error)
	Delete(authToken string, id uint) (err error)

	// Workflow management
	GetDefault(authToken string) (workflow *entity.ApprovalWorkflows, err error)
	SetDefault(authToken string, id uint) (err error)
	ActivateWorkflow(authToken string, id uint) (err error)
	DeactivateWorkflow(authToken string, id uint) (err error)

	// Workflow with steps
	GetWorkflowWithSteps(authToken string, id uint) (workflow *entity.ApprovalWorkflows, steps []*entity.ApprovalWorkflowSteps, err error)
	CreateWorkflowWithSteps(authToken string, workflow *entity.ApprovalWorkflows, steps []*entity.ApprovalWorkflowSteps) (workflowReturn *entity.ApprovalWorkflows, err error)
	UpdateWorkflowWithSteps(authToken string, id uint, workflow *entity.ApprovalWorkflows, steps []*entity.ApprovalWorkflowSteps) (err error)

	// Validation
	ValidateWorkflow(authToken string, workflow *entity.ApprovalWorkflows, steps []*entity.ApprovalWorkflowSteps) (isValid bool, errors []string, err error)
	CanDeleteWorkflow(authToken string, id uint) (canDelete bool, reason string, err error)

	// Comprehensive workflow creation with client settings
	CreateWorkflowWithClientSettings(authToken string, req request.CreateApprovalWorkflowWithClientSettingsRequest) (workflow *entity.ApprovalWorkflows, clientSettings *entity.ClientApprovalSettings, err error)

	// Comprehensive workflow update with client settings
	UpdateWorkflowWithClientSettings(authToken string, req request.UpdateApprovalWorkflowWithClientSettingsRequest) (workflow *entity.ApprovalWorkflows, clientSettings *entity.ClientApprovalSettings, err error)

	// Comprehensive workflow details
	GetComprehensiveWorkflowDetails(authToken string) (details *response.ComprehensiveWorkflowDetailResponse, err error)
}

func NewApprovalWorkflowsService(
	approvalWorkflowsRepository repository.ApprovalWorkflowsRepository,
	approvalWorkflowStepsRepository stepRepo.ApprovalWorkflowStepsRepository,
	clientApprovalSettingsRepository clientApprovalSettingsRepo.ClientApprovalSettingsRepository,
	usersRepository usersRepo.UsersRepository,
	userLevelsRepository userLevelsRepo.UserLevelsRepository,
	userRolesRepository userRolesRepo.UserRolesRepository,
	articleCategoriesRepository articleCategoriesRepo.ArticleCategoriesRepository,
	articleApprovalFlowsRepository articleApprovalFlowsRepo.ArticleApprovalFlowsRepository,
	log zerolog.Logger,
) ApprovalWorkflowsService {
	return &approvalWorkflowsService{
		ApprovalWorkflowsRepository:      approvalWorkflowsRepository,
		ApprovalWorkflowStepsRepository:  approvalWorkflowStepsRepository,
		ClientApprovalSettingsRepository: clientApprovalSettingsRepository,
		UsersRepository:                  usersRepository,
		UserLevelsRepository:             userLevelsRepository,
		UserRolesRepository:              userRolesRepository,
		ArticleCategoriesRepository:      articleCategoriesRepository,
		ArticleApprovalFlowsRepository:   articleApprovalFlowsRepository,
		Log:                              log,
	}
}

// Basic CRUD implementations
func (_i *approvalWorkflowsService) GetAll(authToken string, req request.ApprovalWorkflowsQueryRequest) (workflows []*entity.ApprovalWorkflows, paging paginator.Pagination, err error) {
	// Extract clientId from authToken
	var clientId *uuid.UUID
	if authToken != "" {
		user := utilSvc.GetUserInfo(_i.Log, _i.UsersRepository, authToken)
		if user != nil && user.ClientId != nil {
			clientId = user.ClientId
			_i.Log.Info().Interface("clientId", clientId).Msg("Extracted clientId from auth token")
		}
	}

	if clientId == nil {
		return nil, paginator.Pagination{}, errors.New("clientId not found in auth token")
	}

	return _i.ApprovalWorkflowsRepository.GetAll(clientId, req)
}

func (_i *approvalWorkflowsService) FindOne(authToken string, id uint) (workflow *entity.ApprovalWorkflows, err error) {
	// Extract clientId from authToken
	var clientId *uuid.UUID
	if authToken != "" {
		user := utilSvc.GetUserInfo(_i.Log, _i.UsersRepository, authToken)
		if user != nil && user.ClientId != nil {
			clientId = user.ClientId
			_i.Log.Info().Interface("clientId", clientId).Msg("Extracted clientId from auth token")
		}
	}

	if clientId == nil {
		return nil, errors.New("clientId not found in auth token")
	}

	return _i.ApprovalWorkflowsRepository.FindOne(clientId, id)
}

func (_i *approvalWorkflowsService) Create(authToken string, workflow *entity.ApprovalWorkflows, steps []*entity.ApprovalWorkflowSteps) (workflowReturn *entity.ApprovalWorkflows, err error) {
	// Extract clientId from authToken
	var clientId *uuid.UUID
	if authToken != "" {
		user := utilSvc.GetUserInfo(_i.Log, _i.UsersRepository, authToken)
		if user != nil && user.ClientId != nil {
			clientId = user.ClientId
			_i.Log.Info().Interface("clientId", clientId).Msg("Extracted clientId from auth token")
		}
	}

	if clientId == nil {
		return nil, errors.New("clientId not found in auth token")
	}

	// Validate workflow and steps
	isValid, validationErrors, err := _i.ValidateWorkflow(authToken, workflow, steps)
	if err != nil {
		return nil, err
	}

	if !isValid {
		return nil, errors.New(fmt.Sprintf("Validation failed: %v", validationErrors))
	}

	// Create workflow
	workflowReturn, err = _i.ApprovalWorkflowsRepository.Create(clientId, workflow)
	if err != nil {
		return nil, err
	}

	// Create steps
	for i, step := range steps {
		step.WorkflowId = workflowReturn.ID
		step.StepOrder = i + 1
		_, err = _i.ApprovalWorkflowStepsRepository.Create(clientId, step)
		if err != nil {
			// Rollback workflow creation if step creation fails
			_i.ApprovalWorkflowsRepository.Delete(clientId, workflowReturn.ID)
			return nil, err
		}
	}

	return workflowReturn, nil
}

func (_i *approvalWorkflowsService) Update(authToken string, id uint, workflow *entity.ApprovalWorkflows) (err error) {
	// Extract clientId from authToken
	var clientId *uuid.UUID
	if authToken != "" {
		user := utilSvc.GetUserInfo(_i.Log, _i.UsersRepository, authToken)
		if user != nil && user.ClientId != nil {
			clientId = user.ClientId
			_i.Log.Info().Interface("clientId", clientId).Msg("Extracted clientId from auth token")
		}
	}

	if clientId == nil {
		return errors.New("clientId not found in auth token")
	}

	// Check if workflow exists
	existingWorkflow, err := _i.ApprovalWorkflowsRepository.FindOne(clientId, id)
	if err != nil {
		return err
	}

	if existingWorkflow == nil {
		return errors.New("workflow not found")
	}

	return _i.ApprovalWorkflowsRepository.Update(clientId, id, workflow)
}

func (_i *approvalWorkflowsService) Delete(authToken string, id uint) (err error) {
	// Extract clientId from authToken
	var clientId *uuid.UUID
	if authToken != "" {
		user := utilSvc.GetUserInfo(_i.Log, _i.UsersRepository, authToken)
		if user != nil && user.ClientId != nil {
			clientId = user.ClientId
			_i.Log.Info().Interface("clientId", clientId).Msg("Extracted clientId from auth token")
		}
	}

	if clientId == nil {
		return errors.New("clientId not found in auth token")
	}

	// Check if workflow can be deleted
	canDelete, reason, err := _i.CanDeleteWorkflow(authToken, id)
	if err != nil {
		return err
	}

	if !canDelete {
		return errors.New(reason)
	}

	return _i.ApprovalWorkflowsRepository.Delete(clientId, id)
}

// Workflow management
func (_i *approvalWorkflowsService) GetDefault(authToken string) (workflow *entity.ApprovalWorkflows, err error) {
	// Extract clientId from authToken
	var clientId *uuid.UUID
	if authToken != "" {
		user := utilSvc.GetUserInfo(_i.Log, _i.UsersRepository, authToken)
		if user != nil && user.ClientId != nil {
			clientId = user.ClientId
			_i.Log.Info().Interface("clientId", clientId).Msg("Extracted clientId from auth token")
		}
	}

	if clientId == nil {
		return nil, errors.New("clientId not found in auth token")
	}

	return _i.ApprovalWorkflowsRepository.FindDefault(clientId)
}

func (_i *approvalWorkflowsService) SetDefault(authToken string, id uint) (err error) {
	// Extract clientId from authToken
	var clientId *uuid.UUID
	if authToken != "" {
		user := utilSvc.GetUserInfo(_i.Log, _i.UsersRepository, authToken)
		if user != nil && user.ClientId != nil {
			clientId = user.ClientId
			_i.Log.Info().Interface("clientId", clientId).Msg("Extracted clientId from auth token")
		}
	}

	if clientId == nil {
		return errors.New("clientId not found in auth token")
	}

	// Check if workflow exists and is active
	workflow, err := _i.ApprovalWorkflowsRepository.FindOne(clientId, id)
	if err != nil {
		return err
	}

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

	if workflow.IsActive == nil || !*workflow.IsActive {
		return errors.New("cannot set inactive workflow as default")
	}

	return _i.ApprovalWorkflowsRepository.SetDefault(clientId, id)
}

func (_i *approvalWorkflowsService) ActivateWorkflow(authToken string, id uint) (err error) {
	// Extract clientId from authToken
	var clientId *uuid.UUID
	if authToken != "" {
		user := utilSvc.GetUserInfo(_i.Log, _i.UsersRepository, authToken)
		if user != nil && user.ClientId != nil {
			clientId = user.ClientId
			_i.Log.Info().Interface("clientId", clientId).Msg("Extracted clientId from auth token")
		}
	}

	if clientId == nil {
		return errors.New("clientId not found in auth token")
	}

	// Validate workflow before activation
	workflow, err := _i.ApprovalWorkflowsRepository.FindOne(clientId, id)
	if err != nil {
		return err
	}

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

	// Get workflow steps and validate
	steps, err := _i.ApprovalWorkflowStepsRepository.GetByWorkflowId(clientId, id)
	if err != nil {
		return err
	}

	isValid, validationErrors, err := _i.ValidateWorkflow(authToken, workflow, steps)
	if err != nil {
		return err
	}

	if !isValid {
		return errors.New(fmt.Sprintf("Cannot activate invalid workflow: %v", validationErrors))
	}

	// Activate workflow
	isActive := true
	updateData := &entity.ApprovalWorkflows{IsActive: &isActive}
	return _i.ApprovalWorkflowsRepository.Update(clientId, id, updateData)
}

func (_i *approvalWorkflowsService) DeactivateWorkflow(authToken string, id uint) (err error) {
	// Extract clientId from authToken
	var clientId *uuid.UUID
	if authToken != "" {
		user := utilSvc.GetUserInfo(_i.Log, _i.UsersRepository, authToken)
		if user != nil && user.ClientId != nil {
			clientId = user.ClientId
			_i.Log.Info().Interface("clientId", clientId).Msg("Extracted clientId from auth token")
		}
	}

	if clientId == nil {
		return errors.New("clientId not found in auth token")
	}

	// Check if this is the default workflow
	defaultWorkflow, err := _i.ApprovalWorkflowsRepository.FindDefault(clientId)
	if err != nil {
		return err
	}

	if defaultWorkflow != nil && defaultWorkflow.ID == id {
		return errors.New("cannot deactivate default workflow")
	}

	// Check if workflow is being used in active approval flows
	canDelete, reason, err := _i.CanDeleteWorkflow(authToken, id)
	if err != nil {
		return err
	}

	if !canDelete {
		return errors.New(fmt.Sprintf("Cannot deactivate workflow: %s", reason))
	}

	// Deactivate workflow
	isActive := false
	updateData := &entity.ApprovalWorkflows{IsActive: &isActive}
	return _i.ApprovalWorkflowsRepository.Update(clientId, id, updateData)
}

// Workflow with steps
func (_i *approvalWorkflowsService) GetWorkflowWithSteps(authToken string, id uint) (workflow *entity.ApprovalWorkflows, steps []*entity.ApprovalWorkflowSteps, err error) {
	// Extract clientId from authToken
	var clientId *uuid.UUID
	if authToken != "" {
		user := utilSvc.GetUserInfo(_i.Log, _i.UsersRepository, authToken)
		if user != nil && user.ClientId != nil {
			clientId = user.ClientId
			_i.Log.Info().Interface("clientId", clientId).Msg("Extracted clientId from auth token")
		}
	}

	if clientId == nil {
		return nil, nil, errors.New("clientId not found in auth token")
	}

	workflow, err = _i.ApprovalWorkflowsRepository.FindOne(clientId, id)
	if err != nil {
		return nil, nil, err
	}

	steps, err = _i.ApprovalWorkflowStepsRepository.GetByWorkflowId(clientId, id)
	if err != nil {
		return nil, nil, err
	}

	return workflow, steps, nil
}

func (_i *approvalWorkflowsService) CreateWorkflowWithSteps(authToken string, workflow *entity.ApprovalWorkflows, steps []*entity.ApprovalWorkflowSteps) (workflowReturn *entity.ApprovalWorkflows, err error) {
	// Extract clientId from authToken
	var clientId *uuid.UUID
	if authToken != "" {
		user := utilSvc.GetUserInfo(_i.Log, _i.UsersRepository, authToken)
		if user != nil && user.ClientId != nil {
			clientId = user.ClientId
			_i.Log.Info().Interface("clientId", clientId).Msg("Extracted clientId from auth token")
		}
	}

	if clientId == nil {
		return nil, errors.New("clientId not found in auth token")
	}

	return _i.Create(authToken, workflow, steps)
}

func (_i *approvalWorkflowsService) UpdateWorkflowWithSteps(authToken string, id uint, workflow *entity.ApprovalWorkflows, steps []*entity.ApprovalWorkflowSteps) (err error) {
	// Extract clientId from authToken
	var clientId *uuid.UUID
	if authToken != "" {
		user := utilSvc.GetUserInfo(_i.Log, _i.UsersRepository, authToken)
		if user != nil && user.ClientId != nil {
			clientId = user.ClientId
			_i.Log.Info().Interface("clientId", clientId).Msg("Extracted clientId from auth token")
		}
	}

	if clientId == nil {
		return errors.New("clientId not found in auth token")
	}

	// Update workflow
	err = _i.Update(authToken, id, workflow)
	if err != nil {
		return err
	}

	// Get existing steps
	existingSteps, err := _i.ApprovalWorkflowStepsRepository.GetByWorkflowId(clientId, id)
	if err != nil {
		return err
	}

	// Delete existing steps (simplified approach - in production, you might want to update/merge)
	for _, existingStep := range existingSteps {
		err = _i.ApprovalWorkflowStepsRepository.Delete(clientId, existingStep.ID)
		if err != nil {
			return err
		}
	}

	// Create new steps
	for i, step := range steps {
		step.WorkflowId = id
		step.StepOrder = i + 1
		_, err = _i.ApprovalWorkflowStepsRepository.Create(clientId, step)
		if err != nil {
			return err
		}
	}

	return nil
}

// Validation
func (_i *approvalWorkflowsService) ValidateWorkflow(authToken string, workflow *entity.ApprovalWorkflows, steps []*entity.ApprovalWorkflowSteps) (isValid bool, errors []string, err error) {
	errors = make([]string, 0)

	// Validate workflow
	if workflow.Name == "" {
		errors = append(errors, "Workflow name is required")
	}

	// Validate steps
	if len(steps) == 0 {
		errors = append(errors, "Workflow must have at least one step")
	} else {
		// For multi-branch workflow, we need different validation logic
		_i.validateMultiBranchSteps(steps, &errors)
	}

	isValid = len(errors) == 0
	return isValid, errors, nil
}

// validateMultiBranchSteps validates steps for multi-branch workflow
func (_i *approvalWorkflowsService) validateMultiBranchSteps(steps []*entity.ApprovalWorkflowSteps, errors *[]string) {
	// Group steps by step order to handle parallel branches
	stepOrderGroups := make(map[int][]*entity.ApprovalWorkflowSteps)

	for i, step := range steps {
		// Basic validation for each step
		if step.StepName == "" {
			*errors = append(*errors, fmt.Sprintf("Step %d name is required", i+1))
		}

		if step.RequiredUserLevelId == 0 {
			*errors = append(*errors, fmt.Sprintf("Step %d must have a required user level", i+1))
		}

		if step.StepOrder <= 0 {
			*errors = append(*errors, fmt.Sprintf("Step %d must have a valid step order (greater than 0)", i+1))
		}

		// Validate condition type and value
		if step.ConditionType != nil {
			validConditionTypes := []string{"user_level", "user_level_hierarchy", "always", "custom"}
			isValidConditionType := false
			for _, validType := range validConditionTypes {
				if *step.ConditionType == validType {
					isValidConditionType = true
					break
				}
			}
			if !isValidConditionType {
				*errors = append(*errors, fmt.Sprintf("Step %d has invalid condition type: %s", i+1, *step.ConditionType))
			}

			// Validate condition value format for specific condition types
			if step.ConditionValue != nil && *step.ConditionValue != "" {
				if *step.ConditionType == "user_level_hierarchy" || *step.ConditionType == "user_level" {
					// Try to parse as JSON to validate format
					var conditionData interface{}
					if err := json.Unmarshal([]byte(*step.ConditionValue), &conditionData); err != nil {
						*errors = append(*errors, fmt.Sprintf("Step %d has invalid condition value format: %s", i+1, *step.ConditionValue))
					}
				}
			}
		}

		// Group steps by step order
		stepOrderGroups[step.StepOrder] = append(stepOrderGroups[step.StepOrder], step)
	}

	// Validate step order groups
	maxStepOrder := 0
	for stepOrder, groupSteps := range stepOrderGroups {
		if stepOrder > maxStepOrder {
			maxStepOrder = stepOrder
		}

		// Check for duplicate branch names within the same step order
		branchNames := make(map[string]bool)
		for _, step := range groupSteps {
			if step.BranchName != nil && *step.BranchName != "" {
				if branchNames[*step.BranchName] {
					*errors = append(*errors, fmt.Sprintf("Duplicate branch name '%s' found in step order %d", *step.BranchName, stepOrder))
				}
				branchNames[*step.BranchName] = true
			}
		}

		// Validate branch order within the same step order
		branchOrders := make(map[int]bool)
		for _, step := range groupSteps {
			if step.BranchOrder != nil {
				if branchOrders[*step.BranchOrder] {
					*errors = append(*errors, fmt.Sprintf("Duplicate branch order %d found in step order %d", *step.BranchOrder, stepOrder))
				}
				branchOrders[*step.BranchOrder] = true
			}
		}
	}

	// Validate that we have at least one step with step order 1
	if len(stepOrderGroups[1]) == 0 {
		*errors = append(*errors, "Workflow must have at least one step with step order 1")
	}

	// Validate that step orders are sequential (no gaps)
	for i := 1; i <= maxStepOrder; i++ {
		if len(stepOrderGroups[i]) == 0 {
			*errors = append(*errors, fmt.Sprintf("Missing step order %d - step orders must be sequential", i))
		}
	}
}

func (_i *approvalWorkflowsService) CanDeleteWorkflow(authToken string, id uint) (canDelete bool, reason string, err error) {
	// Extract clientId from authToken
	var clientId *uuid.UUID
	if authToken != "" {
		user := utilSvc.GetUserInfo(_i.Log, _i.UsersRepository, authToken)
		if user != nil && user.ClientId != nil {
			clientId = user.ClientId
			_i.Log.Info().Interface("clientId", clientId).Msg("Extracted clientId from auth token")
		}
	}

	if clientId == nil {
		return false, "clientId not found in auth token", errors.New("clientId not found in auth token")
	}

	// Check if workflow is default
	defaultWorkflow, err := _i.ApprovalWorkflowsRepository.FindDefault(clientId)
	if err != nil {
		return false, "", err
	}

	if defaultWorkflow != nil && defaultWorkflow.ID == id {
		return false, "Cannot delete default workflow", nil
	}

	// Check if workflow is being used in active approval flows
	// This would require a method in ArticleApprovalFlowsRepository
	// For now, we'll assume it can be deleted
	// TODO: Implement check for active approval flows

	return true, "", nil
}

// CreateWorkflowWithClientSettings creates a comprehensive approval workflow with client settings in a single transaction
func (_i *approvalWorkflowsService) CreateWorkflowWithClientSettings(authToken string, req request.CreateApprovalWorkflowWithClientSettingsRequest) (workflow *entity.ApprovalWorkflows, clientSettings *entity.ClientApprovalSettings, err error) {
	// Extract clientId from authToken
	var clientId *uuid.UUID
	if authToken != "" {
		user := utilSvc.GetUserInfo(_i.Log, _i.UsersRepository, authToken)
		if user != nil && user.ClientId != nil {
			clientId = user.ClientId
			_i.Log.Info().Interface("clientId", clientId).Msg("Extracted clientId from auth token")
		}
	}

	if clientId == nil {
		return nil, nil, errors.New("clientId not found in auth token")
	}

	_i.Log.Info().
		Str("workflowName", req.Name).
		Interface("clientId", clientId).
		Msg("Creating comprehensive approval workflow with client settings")

	// Convert request to entities
	workflowEntity := req.ToWorkflowEntity()
	stepsEntity := req.ToStepsEntity()
	clientSettingsEntity := req.ToClientApprovalSettingsEntity()

	// Set client ID for all entities
	workflowEntity.ClientId = clientId
	clientSettingsEntity.ClientId = *clientId

	// Validate workflow and steps
	isValid, validationErrors, err := _i.ValidateWorkflow(authToken, workflowEntity, stepsEntity)
	if err != nil {
		return nil, nil, err
	}

	if !isValid {
		return nil, nil, errors.New(fmt.Sprintf("Validation failed: %v", validationErrors))
	}

	// Check if client approval settings already exist
	existingSettings, err := _i.ClientApprovalSettingsRepository.FindByClientId(*clientId)
	if err != nil {
		return nil, nil, fmt.Errorf("failed to check existing client approval settings: %w", err)
	}

	if existingSettings != nil {
		return nil, nil, errors.New("client approval settings already exist for this client")
	}

	// Create workflow
	workflow, err = _i.ApprovalWorkflowsRepository.Create(clientId, workflowEntity)
	if err != nil {
		return nil, nil, fmt.Errorf("failed to create workflow: %w", err)
	}

	_i.Log.Info().
		Uint("workflowId", workflow.ID).
		Str("workflowName", workflow.Name).
		Msg("Workflow created successfully")

	// Create workflow steps
	for i, step := range stepsEntity {
		step.WorkflowId = workflow.ID
		step.StepOrder = i + 1
		step.ClientId = clientId
		_, err = _i.ApprovalWorkflowStepsRepository.Create(clientId, step)
		if err != nil {
			// Rollback workflow creation if step creation fails
			_i.Log.Error().Err(err).Msg("Failed to create workflow step, rolling back workflow")
			_i.ApprovalWorkflowsRepository.Delete(clientId, workflow.ID)
			return nil, nil, fmt.Errorf("failed to create workflow step %d: %w", i+1, err)
		}
	}

	_i.Log.Info().
		Uint("workflowId", workflow.ID).
		Int("stepsCount", len(stepsEntity)).
		Msg("All workflow steps created successfully")

	// Set the workflow as default in client settings if specified
	if req.IsDefault != nil && *req.IsDefault {
		clientSettingsEntity.DefaultWorkflowId = &workflow.ID
	}

	// Create client approval settings
	clientSettings, err = _i.ClientApprovalSettingsRepository.Create(clientId, clientSettingsEntity)
	if err != nil {
		// Rollback workflow and steps creation if client settings creation fails
		_i.Log.Error().Err(err).Msg("Failed to create client approval settings, rolling back workflow and steps")

		// Delete workflow steps
		for _, step := range stepsEntity {
			_i.ApprovalWorkflowStepsRepository.Delete(clientId, step.ID)
		}

		// Delete workflow
		_i.ApprovalWorkflowsRepository.Delete(clientId, workflow.ID)

		return nil, nil, fmt.Errorf("failed to create client approval settings: %w", err)
	}

	_i.Log.Info().
		Uint("workflowId", workflow.ID).
		Interface("clientId", clientId).
		Msg("Client approval settings created successfully")

	// If this workflow is set as default, update the default workflow setting
	if req.IsDefault != nil && *req.IsDefault {
		err = _i.ApprovalWorkflowsRepository.SetDefault(clientId, workflow.ID)
		if err != nil {
			_i.Log.Warn().Err(err).Msg("Failed to set workflow as default, but workflow and settings were created successfully")
		} else {
			_i.Log.Info().
				Uint("workflowId", workflow.ID).
				Msg("Workflow set as default successfully")
		}
	}

	_i.Log.Info().
		Uint("workflowId", workflow.ID).
		Interface("clientId", clientId).
		Msg("Comprehensive approval workflow with client settings created successfully")

	return workflow, clientSettings, nil
}

// GetComprehensiveWorkflowDetails retrieves comprehensive workflow details including all related data
func (_i *approvalWorkflowsService) GetComprehensiveWorkflowDetails(authToken string) (details *response.ComprehensiveWorkflowDetailResponse, err error) {
	// Extract clientId from authToken
	var clientId *uuid.UUID
	if authToken != "" {
		user := utilSvc.GetUserInfo(_i.Log, _i.UsersRepository, authToken)
		if user != nil && user.ClientId != nil {
			clientId = user.ClientId
			_i.Log.Info().Interface("clientId", clientId).Msg("Extracted clientId from auth token")
		}
	}

	if clientId == nil {
		return nil, errors.New("clientId not found in auth token")
	}

	_i.Log.Info().
		Interface("clientId", clientId).
		Msg("Getting comprehensive workflow details")

	// Get workflow - first try to get default workflow, if not found get any active workflow
	workflow, err := _i.ApprovalWorkflowsRepository.FindDefault(clientId)
	if err != nil || workflow == nil {
		_i.Log.Info().Msg("No default workflow found, getting first active workflow")
		// If no default workflow, get the first active workflow for this client
		queryReq := request.ApprovalWorkflowsQueryRequest{
			Pagination: &paginator.Pagination{
				Limit: 1,
			},
		}
		workflows, _, err := _i.ApprovalWorkflowsRepository.GetAll(clientId, queryReq)
		if err != nil {
			return nil, fmt.Errorf("failed to get workflows: %w", err)
		}
		if len(workflows) == 0 {
			return nil, errors.New("no active workflows found for this client")
		}
		workflow = workflows[0]
	}

	workflowId := workflow.ID

	// Get workflow steps
	steps, err := _i.ApprovalWorkflowStepsRepository.GetByWorkflowId(clientId, workflowId)
	if err != nil {
		return nil, fmt.Errorf("failed to get workflow steps: %w", err)
	}

	// Get client approval settings
	clientSettings, err := _i.ClientApprovalSettingsRepository.FindByClientId(*clientId)
	if err != nil {
		_i.Log.Warn().Err(err).Msg("Failed to get client approval settings")
		// Don't return error, just log warning
	}

	// Build comprehensive response
	details = &response.ComprehensiveWorkflowDetailResponse{
		LastUpdated: workflow.UpdatedAt,
	}

	// Build workflow detail info
	workflowDetail := response.WorkflowDetailInfo{
		ID:               workflow.ID,
		Name:             workflow.Name,
		Description:      workflow.Description,
		IsDefault:        workflow.IsDefault,
		IsActive:         workflow.IsActive,
		RequiresApproval: workflow.RequiresApproval,
		AutoPublish:      workflow.AutoPublish,
		CreatedAt:        workflow.CreatedAt,
		UpdatedAt:        workflow.UpdatedAt,
		TotalSteps:       len(steps),
		MaxStepOrder:     0,
	}

	if workflow.ClientId != nil {
		clientIdStr := workflow.ClientId.String()
		workflowDetail.ClientId = &clientIdStr
	}

	// Calculate workflow statistics
	activeSteps := 0
	hasBranches := false
	for _, step := range steps {
		if step.IsActive != nil && *step.IsActive {
			activeSteps++
		}
		if step.ParentStepId != nil {
			hasBranches = true
		}
		if step.StepOrder > workflowDetail.MaxStepOrder {
			workflowDetail.MaxStepOrder = step.StepOrder
		}
	}

	workflowDetail.ActiveSteps = activeSteps
	workflowDetail.HasBranches = hasBranches
	details.Workflow = workflowDetail

	// Build step details
	stepDetails := make([]response.WorkflowStepDetailInfo, len(steps))
	for i, step := range steps {
		stepDetail := response.WorkflowStepDetailInfo{
			ID:                    step.ID,
			WorkflowId:            step.WorkflowId,
			StepOrder:             step.StepOrder,
			StepName:              step.StepName,
			RequiredUserLevelId:   step.RequiredUserLevelId,
			CanSkip:               step.CanSkip,
			AutoApproveAfterHours: step.AutoApproveAfterHours,
			IsActive:              step.IsActive,
			ParentStepId:          step.ParentStepId,
			ConditionType:         step.ConditionType,
			ConditionValue:        step.ConditionValue,
			IsParallel:            step.IsParallel,
			BranchName:            step.BranchName,
			BranchOrder:           step.BranchOrder,
		}

		// Get user level name
		userLevel, err := _i.UserLevelsRepository.FindOne(clientId, step.RequiredUserLevelId)
		if err == nil && userLevel != nil {
			stepDetail.RequiredUserLevelName = userLevel.Name
		}

		// Get parent step name
		if step.ParentStepId != nil {
			for _, parentStep := range steps {
				if parentStep.ID == *step.ParentStepId {
					stepDetail.ParentStepName = &parentStep.StepName
					break
				}
			}
		}

		// Check if step has children
		hasChildren := false
		for _, childStep := range steps {
			if childStep.ParentStepId != nil && *childStep.ParentStepId == step.ID {
				hasChildren = true
				break
			}
		}
		stepDetail.HasChildren = hasChildren

		// Check if first/last step
		stepDetail.IsFirstStep = step.StepOrder == 1
		stepDetail.IsLastStep = step.StepOrder == workflowDetail.MaxStepOrder

		stepDetails[i] = stepDetail
	}

	details.Steps = stepDetails

	// Build client settings detail
	if clientSettings != nil {
		clientSettingsDetail := response.ClientApprovalSettingsDetail{
			ID:                       clientSettings.ID,
			ClientId:                 clientSettings.ClientId.String(),
			RequiresApproval:         clientSettings.RequiresApproval,
			DefaultWorkflowId:        clientSettings.DefaultWorkflowId,
			AutoPublishArticles:      clientSettings.AutoPublishArticles,
			ApprovalExemptUsers:      clientSettings.ApprovalExemptUsers,
			ApprovalExemptRoles:      clientSettings.ApprovalExemptRoles,
			ApprovalExemptCategories: clientSettings.ApprovalExemptCategories,
			RequireApprovalFor:       clientSettings.RequireApprovalFor,
			SkipApprovalFor:          clientSettings.SkipApprovalFor,
			IsActive:                 clientSettings.IsActive,
			CreatedAt:                clientSettings.CreatedAt,
			UpdatedAt:                clientSettings.UpdatedAt,
		}

		// Set default workflow name
		if clientSettings.DefaultWorkflowId != nil {
			defaultWorkflow, err := _i.ApprovalWorkflowsRepository.FindOne(clientId, *clientSettings.DefaultWorkflowId)
			if err == nil && defaultWorkflow != nil {
				clientSettingsDetail.DefaultWorkflowName = &defaultWorkflow.Name
			}
		}

		// Get exempt users details
		exemptUsersDetails := make([]response.UserDetailInfo, 0)
		for _, userId := range clientSettings.ApprovalExemptUsers {
			user, err := _i.UsersRepository.FindOne(clientId, userId)
			if err == nil && user != nil {
				userLevel, _ := _i.UserLevelsRepository.FindOne(clientId, user.UserLevelId)
				userLevelName := ""
				if userLevel != nil {
					userLevelName = userLevel.Name
				}
				exemptUsersDetails = append(exemptUsersDetails, response.UserDetailInfo{
					ID:            user.ID,
					Username:      user.Username,
					Fullname:      user.Fullname,
					Email:         user.Email,
					UserLevelId:   user.UserLevelId,
					UserLevelName: userLevelName,
					IsActive:      user.IsActive,
				})
			}
		}
		clientSettingsDetail.ExemptUsersDetails = exemptUsersDetails

		// Get exempt roles details
		exemptRolesDetails := make([]response.UserRoleDetailInfo, 0)
		for _, roleId := range clientSettings.ApprovalExemptRoles {
			role, err := _i.UserRolesRepository.FindOne(roleId)
			if err == nil && role != nil {
				exemptRolesDetails = append(exemptRolesDetails, response.UserRoleDetailInfo{
					ID:       role.ID,
					RoleName: role.Name,
					IsActive: role.IsActive,
				})
			}
		}
		clientSettingsDetail.ExemptRolesDetails = exemptRolesDetails

		// Get exempt categories details
		exemptCategoriesDetails := make([]response.CategoryDetailInfo, 0)
		for _, categoryId := range clientSettings.ApprovalExemptCategories {
			category, err := _i.ArticleCategoriesRepository.FindOne(clientId, categoryId)
			if err == nil && category != nil {
				exemptCategoriesDetails = append(exemptCategoriesDetails, response.CategoryDetailInfo{
					ID:           category.ID,
					CategoryName: category.Title,
					IsActive:     category.IsActive,
				})
			}
		}
		clientSettingsDetail.ExemptCategoriesDetails = exemptCategoriesDetails

		details.ClientSettings = clientSettingsDetail
	}

	// Build related data
	relatedData := response.RelatedDataInfo{}

	// Get all user levels for this client
	userLevels, _, err := _i.UserLevelsRepository.GetAll(clientId, userLevelsReq.UserLevelsQueryRequest{
		Pagination: &paginator.Pagination{},
	})
	if err == nil {
		userLevelDetails := make([]response.UserLevelDetailInfo, len(userLevels))
		for i, level := range userLevels {
			userLevelDetails[i] = response.UserLevelDetailInfo{
				ID:               level.ID,
				Name:             level.Name,
				AliasName:        level.AliasName,
				LevelNumber:      level.LevelNumber,
				IsApprovalActive: level.IsApprovalActive,
				IsActive:         level.IsActive,
			}
		}
		relatedData.UserLevels = userLevelDetails
	}

	// Get workflow statistics (simplified - would need more complex queries in real implementation)
	statistics := response.WorkflowStatisticsInfo{
		TotalArticlesProcessed: 0,   // Would need to query article_approval_flows
		PendingArticles:        0,   // Would need to query active flows
		ApprovedArticles:       0,   // Would need to query completed flows
		RejectedArticles:       0,   // Would need to query rejected flows
		AverageProcessingTime:  0,   // Would need to calculate from flow durations
		MostActiveStep:         "",  // Would need to analyze step activity
		LastUsedAt:             nil, // Would need to query last flow creation
	}

	details.Statistics = statistics
	details.RelatedData = relatedData

	_i.Log.Info().
		Uint("workflowId", workflowId).
		Int("stepsCount", len(steps)).
		Msg("Comprehensive workflow details retrieved successfully")

	return details, nil
}

// UpdateWorkflowWithClientSettings updates a comprehensive approval workflow with client settings in a single transaction
func (_i *approvalWorkflowsService) UpdateWorkflowWithClientSettings(authToken string, req request.UpdateApprovalWorkflowWithClientSettingsRequest) (workflow *entity.ApprovalWorkflows, clientSettings *entity.ClientApprovalSettings, err error) {
	// Extract clientId from authToken
	var clientId *uuid.UUID
	if authToken != "" {
		user := utilSvc.GetUserInfo(_i.Log, _i.UsersRepository, authToken)
		if user != nil && user.ClientId != nil {
			clientId = user.ClientId
			_i.Log.Info().Interface("clientId", clientId).Msg("Extracted clientId from auth token")
		}
	}

	if clientId == nil {
		return nil, nil, errors.New("clientId not found in auth token")
	}

	_i.Log.Info().
		Uint("workflowId", req.WorkflowId).
		Interface("clientId", clientId).
		Msg("Updating comprehensive approval workflow with client settings")

	// Check if workflow exists
	existingWorkflow, err := _i.ApprovalWorkflowsRepository.FindOne(clientId, req.WorkflowId)
	if err != nil {
		return nil, nil, fmt.Errorf("failed to find workflow: %w", err)
	}
	if existingWorkflow == nil {
		return nil, nil, errors.New("workflow not found")
	}

	// Convert request to entities
	workflowEntity := req.ToWorkflowEntity()
	stepsEntity := req.ToStepsEntity()
	clientSettingsEntity := req.ToClientApprovalSettingsEntity()

	// Validate workflow and steps
	isValid, validationErrors, err := _i.ValidateWorkflow(authToken, workflowEntity, stepsEntity)
	if err != nil {
		return nil, nil, err
	}
	if !isValid {
		return nil, nil, fmt.Errorf("validation failed: %v", validationErrors)
	}

	// Start transaction-like operations with rollback capability
	// Update workflow
	err = _i.ApprovalWorkflowsRepository.Update(clientId, req.WorkflowId, workflowEntity)
	if err != nil {
		_i.Log.Error().Err(err).Uint("workflowId", req.WorkflowId).Msg("Failed to update workflow")
		return nil, nil, fmt.Errorf("failed to update workflow: %w", err)
	}
	_i.Log.Info().Uint("workflowId", req.WorkflowId).Msg("Workflow updated successfully")

	// Delete existing steps and create new ones
	existingSteps, err := _i.ApprovalWorkflowStepsRepository.GetByWorkflowId(clientId, req.WorkflowId)
	if err != nil {
		_i.Log.Error().Err(err).Uint("workflowId", req.WorkflowId).Msg("Failed to get existing workflow steps")
		return nil, nil, fmt.Errorf("failed to get existing workflow steps: %w", err)
	}

	for _, step := range existingSteps {
		err = _i.ApprovalWorkflowStepsRepository.Delete(clientId, step.ID)
		if err != nil {
			_i.Log.Error().Err(err).Uint("workflowId", req.WorkflowId).Uint("stepId", step.ID).Msg("Failed to delete existing workflow step")
			return nil, nil, fmt.Errorf("failed to delete existing workflow step %d: %w", step.ID, err)
		}
	}

	// Create new workflow steps
	for i, step := range stepsEntity {
		step.WorkflowId = req.WorkflowId
		step.StepOrder = i + 1
		step.ClientId = clientId
		_, err = _i.ApprovalWorkflowStepsRepository.Create(clientId, step)
		if err != nil {
			_i.Log.Error().Err(err).Uint("workflowId", req.WorkflowId).Int("stepOrder", i+1).Msg("Failed to create workflow step")
			// Rollback: delete the workflow
			_i.ApprovalWorkflowsRepository.Delete(clientId, req.WorkflowId)
			return nil, nil, fmt.Errorf("failed to create workflow step %d: %w", i+1, err)
		}
	}
	_i.Log.Info().Uint("workflowId", req.WorkflowId).Int("stepsCount", len(stepsEntity)).Msg("Workflow steps updated successfully")

	// Set the workflow as default in client settings if specified
	if req.IsDefault != nil && *req.IsDefault {
		clientSettingsEntity.DefaultWorkflowId = &req.WorkflowId
	}

	// Update or create client approval settings
	existingClientSettings, err := _i.ClientApprovalSettingsRepository.FindByClientId(*clientId)
	if err != nil {
		_i.Log.Warn().Err(err).Interface("clientId", clientId).Msg("Failed to find existing client approval settings, will create new")
		// Create new client settings
		clientSettingsEntity.ClientId = *clientId
		clientSettings, err = _i.ClientApprovalSettingsRepository.Create(clientId, clientSettingsEntity)
		if err != nil {
			_i.Log.Error().Err(err).Interface("clientId", clientId).Msg("Failed to create client approval settings")
			// Rollback: delete the workflow and steps
			rollbackSteps, _ := _i.ApprovalWorkflowStepsRepository.GetByWorkflowId(clientId, req.WorkflowId)
			for _, step := range rollbackSteps {
				_i.ApprovalWorkflowStepsRepository.Delete(clientId, step.ID)
			}
			_i.ApprovalWorkflowsRepository.Delete(clientId, req.WorkflowId)
			return nil, nil, fmt.Errorf("failed to create client approval settings: %w", err)
		}
	} else {
		// Update existing client settings
		clientSettingsEntity.ID = existingClientSettings.ID
		clientSettingsEntity.ClientId = *clientId
		clientSettingsEntity.CreatedAt = existingClientSettings.CreatedAt
		clientSettings, err = _i.ClientApprovalSettingsRepository.Update(clientId, clientSettingsEntity)
		if err != nil {
			_i.Log.Error().Err(err).Uint("clientSettingsId", existingClientSettings.ID).Msg("Failed to update client approval settings")
			// Rollback: delete the workflow and steps
			rollbackSteps, _ := _i.ApprovalWorkflowStepsRepository.GetByWorkflowId(clientId, req.WorkflowId)
			for _, step := range rollbackSteps {
				_i.ApprovalWorkflowStepsRepository.Delete(clientId, step.ID)
			}
			_i.ApprovalWorkflowsRepository.Delete(clientId, req.WorkflowId)
			return nil, nil, fmt.Errorf("failed to update client approval settings: %w", err)
		}
	}
	_i.Log.Info().Interface("clientId", clientId).Msg("Client approval settings updated successfully")

	// If this workflow is set as default, update the default workflow setting
	if req.IsDefault != nil && *req.IsDefault {
		err = _i.ApprovalWorkflowsRepository.SetDefault(clientId, req.WorkflowId)
		if err != nil {
			_i.Log.Warn().Err(err).Uint("workflowId", req.WorkflowId).Msg("Failed to set workflow as default")
			// Don't fail the entire operation for this
		} else {
			_i.Log.Info().Uint("workflowId", req.WorkflowId).Msg("Workflow set as default successfully")
		}
	}

	workflow, err = _i.ApprovalWorkflowsRepository.FindOne(clientId, req.WorkflowId)
	if err != nil {
		return nil, nil, fmt.Errorf("failed to get workflow: %w", err)
	}

	_i.Log.Info().
		Uint("workflowId", workflow.ID).
		Interface("clientId", clientId).
		Msg("Comprehensive approval workflow with client settings updated successfully")

	return workflow, clientSettings, nil
}
