package service

import (
	"fmt"
	"web-qudo-be/app/database/entity"
	"web-qudo-be/app/module/client_approval_settings/mapper"
	"web-qudo-be/app/module/client_approval_settings/repository"
	"web-qudo-be/app/module/client_approval_settings/request"
	"web-qudo-be/app/module/client_approval_settings/response"

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

type clientApprovalSettingsService struct {
	clientApprovalSettingsRepo repository.ClientApprovalSettingsRepository
	Log                        zerolog.Logger
}

type ClientApprovalSettingsService interface {
	GetByClientId(clientId *uuid.UUID) (*response.ClientApprovalSettingsResponse, error)
	Create(clientId *uuid.UUID, req request.CreateClientApprovalSettingsRequest) (*response.ClientApprovalSettingsResponse, error)
	Update(clientId *uuid.UUID, req request.UpdateClientApprovalSettingsRequest) (*response.ClientApprovalSettingsResponse, error)
	Delete(clientId *uuid.UUID) error
	ToggleApprovalRequirement(clientId *uuid.UUID, requiresApproval bool) error
	SetDefaultWorkflow(clientId *uuid.UUID, workflowId *uint) error
	AddExemptUser(clientId *uuid.UUID, userId uint) error
	RemoveExemptUser(clientId *uuid.UUID, userId uint) error
	AddExemptRole(clientId *uuid.UUID, roleId uint) error
	RemoveExemptRole(clientId *uuid.UUID, roleId uint) error
	AddExemptCategory(clientId *uuid.UUID, categoryId uint) error
	RemoveExemptCategory(clientId *uuid.UUID, categoryId uint) error
	CheckIfApprovalRequired(clientId *uuid.UUID, userId uint, userLevelId uint, categoryId uint, contentType string) (bool, error)

	// Enhanced methods for dynamic approval management
	EnableApprovalWithTransition(clientId *uuid.UUID, defaultWorkflowId *uint) error
	DisableApprovalWithAutoPublish(clientId *uuid.UUID, reason string) error
	HandlePendingApprovalsOnDisable(clientId *uuid.UUID, action string) error // "auto_approve", "keep_pending", "reset_to_draft"
}

func NewClientApprovalSettingsService(
	clientApprovalSettingsRepo repository.ClientApprovalSettingsRepository,
	log zerolog.Logger,
) ClientApprovalSettingsService {
	return &clientApprovalSettingsService{
		clientApprovalSettingsRepo: clientApprovalSettingsRepo,
		Log:                        log,
	}
}

func (_i *clientApprovalSettingsService) GetByClientId(clientId *uuid.UUID) (*response.ClientApprovalSettingsResponse, error) {
	settings, err := _i.clientApprovalSettingsRepo.FindByClientId(*clientId)
	if err != nil {
		return nil, err
	}

	if settings == nil {
		// Return default settings if none found
		return &response.ClientApprovalSettingsResponse{
			ClientId:                 clientId.String(),
			RequiresApproval:         true, // Default to requiring approval
			AutoPublishArticles:      false,
			ApprovalExemptUsers:      []uint{},
			ApprovalExemptRoles:      []uint{},
			ApprovalExemptCategories: []uint{},
			RequireApprovalFor:       []string{},
			SkipApprovalFor:          []string{},
			IsActive:                 true,
		}, nil
	}

	return mapper.ClientApprovalSettingsResponseMapper(_i.Log, clientId, settings), nil
}

func (_i *clientApprovalSettingsService) Create(clientId *uuid.UUID, req request.CreateClientApprovalSettingsRequest) (*response.ClientApprovalSettingsResponse, error) {
	// Check if settings already exist
	existing, err := _i.clientApprovalSettingsRepo.FindByClientId(*clientId)
	if err != nil {
		return nil, err
	}

	if existing != nil {
		return nil, fmt.Errorf("approval settings already exist for this client")
	}

	// Create new settings
	settings := &entity.ClientApprovalSettings{
		RequiresApproval:         &req.RequiresApproval,
		DefaultWorkflowId:        req.DefaultWorkflowId,
		AutoPublishArticles:      &req.AutoPublishArticles,
		ApprovalExemptUsers:      req.ApprovalExemptUsers,
		ApprovalExemptRoles:      req.ApprovalExemptRoles,
		ApprovalExemptCategories: req.ApprovalExemptCategories,
		RequireApprovalFor:       req.RequireApprovalFor,
		SkipApprovalFor:          req.SkipApprovalFor,
		IsActive:                 &req.IsActive,
	}

	createdSettings, err := _i.clientApprovalSettingsRepo.Create(clientId, settings)
	if err != nil {
		return nil, err
	}

	return mapper.ClientApprovalSettingsResponseMapper(_i.Log, clientId, createdSettings), nil
}

func (_i *clientApprovalSettingsService) Update(clientId *uuid.UUID, req request.UpdateClientApprovalSettingsRequest) (*response.ClientApprovalSettingsResponse, error) {
	// Get existing settings
	settings, err := _i.clientApprovalSettingsRepo.FindByClientId(*clientId)
	if err != nil {
		return nil, err
	}

	if settings == nil {
		return nil, fmt.Errorf("approval settings not found for this client")
	}

	// Update fields if provided
	if req.RequiresApproval != nil {
		settings.RequiresApproval = req.RequiresApproval
	}
	if req.DefaultWorkflowId != nil {
		settings.DefaultWorkflowId = *req.DefaultWorkflowId
	}
	if req.AutoPublishArticles != nil {
		settings.AutoPublishArticles = req.AutoPublishArticles
	}
	if req.ApprovalExemptUsers != nil {
		settings.ApprovalExemptUsers = req.ApprovalExemptUsers
	}
	if req.ApprovalExemptRoles != nil {
		settings.ApprovalExemptRoles = req.ApprovalExemptRoles
	}
	if req.ApprovalExemptCategories != nil {
		settings.ApprovalExemptCategories = req.ApprovalExemptCategories
	}
	if req.RequireApprovalFor != nil {
		settings.RequireApprovalFor = req.RequireApprovalFor
	}
	if req.SkipApprovalFor != nil {
		settings.SkipApprovalFor = req.SkipApprovalFor
	}
	if req.IsActive != nil {
		settings.IsActive = req.IsActive
	}

	updatedSettings, err := _i.clientApprovalSettingsRepo.Update(clientId, settings)
	if err != nil {
		return nil, err
	}

	return mapper.ClientApprovalSettingsResponseMapper(_i.Log, clientId, updatedSettings), nil
}

func (_i *clientApprovalSettingsService) Delete(clientId *uuid.UUID) error {
	return _i.clientApprovalSettingsRepo.Delete(clientId)
}

func (_i *clientApprovalSettingsService) ToggleApprovalRequirement(clientId *uuid.UUID, requiresApproval bool) error {
	settings, err := _i.clientApprovalSettingsRepo.FindByClientId(*clientId)
	if err != nil {
		return err
	}

	if settings == nil {
		return fmt.Errorf("approval settings not found for this client")
	}

	settings.RequiresApproval = &requiresApproval
	_, err = _i.clientApprovalSettingsRepo.Update(clientId, settings)
	return err
}

func (_i *clientApprovalSettingsService) SetDefaultWorkflow(clientId *uuid.UUID, workflowId *uint) error {
	settings, err := _i.clientApprovalSettingsRepo.FindByClientId(*clientId)
	if err != nil {
		return err
	}

	if settings == nil {
		return fmt.Errorf("approval settings not found for this client")
	}

	settings.DefaultWorkflowId = workflowId
	_, err = _i.clientApprovalSettingsRepo.Update(clientId, settings)
	return err
}

func (_i *clientApprovalSettingsService) AddExemptUser(clientId *uuid.UUID, userId uint) error {
	return _i.clientApprovalSettingsRepo.AddExemptUser(clientId, userId)
}

func (_i *clientApprovalSettingsService) RemoveExemptUser(clientId *uuid.UUID, userId uint) error {
	return _i.clientApprovalSettingsRepo.RemoveExemptUser(clientId, userId)
}

func (_i *clientApprovalSettingsService) AddExemptRole(clientId *uuid.UUID, roleId uint) error {
	return _i.clientApprovalSettingsRepo.AddExemptRole(clientId, roleId)
}

func (_i *clientApprovalSettingsService) RemoveExemptRole(clientId *uuid.UUID, roleId uint) error {
	return _i.clientApprovalSettingsRepo.RemoveExemptRole(clientId, roleId)
}

func (_i *clientApprovalSettingsService) AddExemptCategory(clientId *uuid.UUID, categoryId uint) error {
	return _i.clientApprovalSettingsRepo.AddExemptCategory(clientId, categoryId)
}

func (_i *clientApprovalSettingsService) RemoveExemptCategory(clientId *uuid.UUID, categoryId uint) error {
	return _i.clientApprovalSettingsRepo.RemoveExemptCategory(clientId, categoryId)
}

func (_i *clientApprovalSettingsService) CheckIfApprovalRequired(clientId *uuid.UUID, userId uint, userLevelId uint, categoryId uint, contentType string) (bool, error) {
	settings, err := _i.clientApprovalSettingsRepo.FindActiveSettings(clientId)
	if err != nil {
		return true, err // Default to requiring approval on error
	}

	if settings == nil {
		return true, nil // Default to requiring approval if no settings
	}

	// Check if approval is disabled
	if settings.RequiresApproval != nil && !*settings.RequiresApproval {
		return false, nil
	}

	// Check user exemption
	for _, exemptUserId := range settings.ApprovalExemptUsers {
		if exemptUserId == userId {
			return false, nil
		}
	}

	// Check role exemption
	for _, exemptRoleId := range settings.ApprovalExemptRoles {
		if exemptRoleId == userLevelId {
			return false, nil
		}
	}

	// Check category exemption
	for _, exemptCategoryId := range settings.ApprovalExemptCategories {
		if exemptCategoryId == categoryId {
			return false, nil
		}
	}

	// Check content type exemptions
	for _, skipType := range settings.SkipApprovalFor {
		if skipType == contentType {
			return false, nil
		}
	}

	// Check if content type requires approval
	for _, requireType := range settings.RequireApprovalFor {
		if requireType == contentType {
			return true, nil
		}
	}

	// Default to requiring approval
	return true, nil
}

func (_i *clientApprovalSettingsService) EnableApprovalWithTransition(clientId *uuid.UUID, defaultWorkflowId *uint) error {
	settings, err := _i.clientApprovalSettingsRepo.FindByClientId(*clientId)
	if err != nil {
		return err
	}

	if settings == nil {
		// Create new settings
		settings = &entity.ClientApprovalSettings{
			RequiresApproval:    &[]bool{true}[0],
			DefaultWorkflowId:   defaultWorkflowId,
			AutoPublishArticles: &[]bool{false}[0],
			IsActive:            &[]bool{true}[0],
		}
		_, err = _i.clientApprovalSettingsRepo.Create(clientId, settings)
	} else {
		// Update existing settings
		settings.RequiresApproval = &[]bool{true}[0]
		settings.DefaultWorkflowId = defaultWorkflowId
		settings.AutoPublishArticles = &[]bool{false}[0]
		settings.IsActive = &[]bool{true}[0]
		_, err = _i.clientApprovalSettingsRepo.Update(clientId, settings)
	}

	return err
}

func (_i *clientApprovalSettingsService) DisableApprovalWithAutoPublish(clientId *uuid.UUID, reason string) error {
	settings, err := _i.clientApprovalSettingsRepo.FindByClientId(*clientId)
	if err != nil {
		return err
	}

	if settings == nil {
		return fmt.Errorf("approval settings not found for this client")
	}

	settings.RequiresApproval = &[]bool{false}[0]
	settings.AutoPublishArticles = &[]bool{true}[0]
	settings.IsActive = &[]bool{true}[0]

	_, err = _i.clientApprovalSettingsRepo.Update(clientId, settings)
	return err
}

func (_i *clientApprovalSettingsService) HandlePendingApprovalsOnDisable(clientId *uuid.UUID, action string) error {
	// This would typically interact with article approval flows
	// For now, just log the action
	_i.Log.Info().
		Str("client_id", clientId.String()).
		Str("action", action).
		Msg("Handling pending approvals on disable")

	// TODO: Implement actual logic based on action:
	// - "auto_approve": Auto approve all pending articles
	// - "keep_pending": Keep articles in pending state
	// - "reset_to_draft": Reset articles to draft state

	return nil
}
