package shop

import (
	"context"

	"github.com/break/junhong_cmp_fiber/internal/model"
	"github.com/break/junhong_cmp_fiber/internal/model/dto"
	"github.com/break/junhong_cmp_fiber/internal/store"
	"github.com/break/junhong_cmp_fiber/internal/store/postgres"
	"github.com/break/junhong_cmp_fiber/pkg/constants"
	"github.com/break/junhong_cmp_fiber/pkg/errors"
	"github.com/break/junhong_cmp_fiber/pkg/middleware"
	"gorm.io/gorm"
)

type Service struct {
	shopStore     *postgres.ShopStore
	accountStore  *postgres.AccountStore
	shopRoleStore *postgres.ShopRoleStore
	roleStore     *postgres.RoleStore
}

func New(
	shopStore *postgres.ShopStore,
	accountStore *postgres.AccountStore,
	shopRoleStore *postgres.ShopRoleStore,
	roleStore *postgres.RoleStore,
) *Service {
	return &Service{
		shopStore:     shopStore,
		accountStore:  accountStore,
		shopRoleStore: shopRoleStore,
		roleStore:     roleStore,
	}
}

func (s *Service) Update(ctx context.Context, id uint, req *dto.UpdateShopRequest) (*dto.ShopResponse, error) {
	currentUserID := middleware.GetUserIDFromContext(ctx)
	if currentUserID == 0 {
		return nil, errors.New(errors.CodeUnauthorized, "未授权访问")
	}

	shop, err := s.shopStore.GetByID(ctx, id)
	if err != nil {
		return nil, errors.New(errors.CodeShopNotFound, "店铺不存在")
	}

	shop.ShopName = req.ShopName
	shop.ContactName = req.ContactName
	shop.ContactPhone = req.ContactPhone
	shop.Province = req.Province
	shop.City = req.City
	shop.District = req.District
	shop.Address = req.Address
	shop.Status = req.Status
	shop.Updater = currentUserID

	if err := s.shopStore.Update(ctx, shop); err != nil {
		return nil, err
	}

	parentShopName := ""
	if shop.ParentID != nil {
		parentShop, err := s.shopStore.GetByID(ctx, *shop.ParentID)
		if err == nil {
			parentShopName = parentShop.ShopName
		}
	}

	return &dto.ShopResponse{
		ID:             shop.ID,
		ShopName:       shop.ShopName,
		ShopCode:       shop.ShopCode,
		ParentID:       shop.ParentID,
		ParentShopName: parentShopName,
		Level:          shop.Level,
		ContactName:    shop.ContactName,
		ContactPhone:   shop.ContactPhone,
		Province:       shop.Province,
		City:           shop.City,
		District:       shop.District,
		Address:        shop.Address,
		Status:         shop.Status,
		StatusName:     constants.GetStatusName(shop.Status),
		CreatedAt:      shop.CreatedAt.Format("2006-01-02 15:04:05"),
		UpdatedAt:      shop.UpdatedAt.Format("2006-01-02 15:04:05"),
	}, nil
}

// Disable 禁用店铺
func (s *Service) Disable(ctx context.Context, id uint) error {
	// 获取当前用户 ID
	currentUserID := middleware.GetUserIDFromContext(ctx)
	if currentUserID == 0 {
		return errors.New(errors.CodeUnauthorized, "未授权访问")
	}

	// 查询店铺
	shop, err := s.shopStore.GetByID(ctx, id)
	if err != nil {
		return errors.New(errors.CodeShopNotFound, "店铺不存在")
	}

	// 更新状态
	shop.Status = constants.StatusDisabled
	shop.Updater = currentUserID

	return s.shopStore.Update(ctx, shop)
}

// Enable 启用店铺
func (s *Service) Enable(ctx context.Context, id uint) error {
	// 获取当前用户 ID
	currentUserID := middleware.GetUserIDFromContext(ctx)
	if currentUserID == 0 {
		return errors.New(errors.CodeUnauthorized, "未授权访问")
	}

	// 查询店铺
	shop, err := s.shopStore.GetByID(ctx, id)
	if err != nil {
		return errors.New(errors.CodeShopNotFound, "店铺不存在")
	}

	// 更新状态
	shop.Status = constants.StatusEnabled
	shop.Updater = currentUserID

	return s.shopStore.Update(ctx, shop)
}

// GetByID 获取店铺详情
func (s *Service) GetByID(ctx context.Context, id uint) (*model.Shop, error) {
	shop, err := s.shopStore.GetByID(ctx, id)
	if err != nil {
		return nil, errors.New(errors.CodeShopNotFound, "店铺不存在")
	}
	return shop, nil
}

func (s *Service) ListShopResponses(ctx context.Context, req *dto.ShopListRequest) ([]*dto.ShopResponse, int64, error) {
	opts := &store.QueryOptions{
		Page:     req.Page,
		PageSize: req.PageSize,
		OrderBy:  "created_at DESC",
	}
	if opts.Page == 0 {
		opts.Page = 1
	}
	if opts.PageSize == 0 {
		opts.PageSize = constants.DefaultPageSize
	}

	filters := make(map[string]interface{})
	if req.ShopName != "" {
		filters["shop_name"] = req.ShopName
	}
	if req.ShopCode != "" {
		filters["shop_code"] = req.ShopCode
	}
	if req.ContactPhone != "" {
		filters["contact_phone"] = req.ContactPhone
	}
	if req.ParentID != nil {
		filters["parent_id"] = *req.ParentID
	}
	if req.Level != nil {
		filters["level"] = *req.Level
	}
	if req.Status != nil {
		filters["status"] = *req.Status
	}

	shops, total, err := s.shopStore.List(ctx, opts, filters)
	if err != nil {
		return nil, 0, errors.Wrap(errors.CodeInternalError, err, "查询店铺列表失败")
	}

	parentShopNameMap, err := s.buildParentShopNameMap(ctx, shops)
	if err != nil {
		return nil, 0, errors.Wrap(errors.CodeInternalError, err, "查询上级店铺名称失败")
	}

	responses := make([]*dto.ShopResponse, 0, len(shops))
	for _, shop := range shops {
		parentShopName := ""
		if shop.ParentID != nil {
			parentShopName = parentShopNameMap[*shop.ParentID]
		}

		responses = append(responses, &dto.ShopResponse{
			ID:             shop.ID,
			ShopName:       shop.ShopName,
			ShopCode:       shop.ShopCode,
			ParentID:       shop.ParentID,
			ParentShopName: parentShopName,
			Level:          shop.Level,
			ContactName:    shop.ContactName,
			ContactPhone:   shop.ContactPhone,
			Province:       shop.Province,
			City:           shop.City,
			District:       shop.District,
			Address:        shop.Address,
			Status:         shop.Status,
			StatusName:     constants.GetStatusName(shop.Status),
			CreatedAt:      shop.CreatedAt.Format("2006-01-02 15:04:05"),
			UpdatedAt:      shop.UpdatedAt.Format("2006-01-02 15:04:05"),
		})
	}

	return responses, total, nil
}

// buildParentShopNameMap 批量查询店铺上级名称，避免列表接口出现 N+1 查询。
func (s *Service) buildParentShopNameMap(ctx context.Context, shops []*model.Shop) (map[uint]string, error) {
	parentIDs := make([]uint, 0, len(shops))
	parentIDSet := make(map[uint]struct{}, len(shops))
	for _, shop := range shops {
		if shop.ParentID == nil {
			continue
		}
		if _, exists := parentIDSet[*shop.ParentID]; exists {
			continue
		}
		parentIDSet[*shop.ParentID] = struct{}{}
		parentIDs = append(parentIDs, *shop.ParentID)
	}

	if len(parentIDs) == 0 {
		return map[uint]string{}, nil
	}

	parentShops, err := s.shopStore.GetByIDs(ctx, parentIDs)
	if err != nil {
		return nil, err
	}

	parentShopNameMap := make(map[uint]string, len(parentShops))
	for _, parentShop := range parentShops {
		parentShopNameMap[parentShop.ID] = parentShop.ShopName
	}
	return parentShopNameMap, nil
}

func (s *Service) List(ctx context.Context, opts *store.QueryOptions, filters map[string]interface{}) ([]*model.Shop, int64, error) {
	return s.shopStore.List(ctx, opts, filters)
}

// ListCascade 联级查询店铺，用于新增店铺或其他场景选择上级店铺
func (s *Service) ListCascade(ctx context.Context, req *dto.ShopCascadeRequest) ([]*dto.ShopCascadeItem, error) {
	shops, err := s.shopStore.ListForCascade(ctx, req.ShopName, req.ParentID, req.ExcludeSelf)
	if err != nil {
		return nil, errors.Wrap(errors.CodeInternalError, err, "查询店铺失败")
	}

	if len(shops) == 0 {
		return []*dto.ShopCascadeItem{}, nil
	}

	ids := make([]uint, 0, len(shops))
	for _, shop := range shops {
		ids = append(ids, shop.ID)
	}

	childParentIDs, err := s.shopStore.GetParentIDsWithChildren(ctx, ids)
	if err != nil {
		return nil, errors.Wrap(errors.CodeInternalError, err, "查询下级店铺失败")
	}

	hasChildrenSet := make(map[uint]bool, len(childParentIDs))
	for _, pid := range childParentIDs {
		hasChildrenSet[pid] = true
	}

	result := make([]*dto.ShopCascadeItem, 0, len(shops))
	for _, shop := range shops {
		result = append(result, &dto.ShopCascadeItem{
			ID:          shop.ID,
			ShopName:    shop.ShopName,
			HasChildren: hasChildrenSet[shop.ID],
		})
	}

	return result, nil
}

func (s *Service) Delete(ctx context.Context, id uint) error {
	currentUserID := middleware.GetUserIDFromContext(ctx)
	if currentUserID == 0 {
		return errors.New(errors.CodeUnauthorized, "未授权访问")
	}

	shop, err := s.shopStore.GetByID(ctx, id)
	if err != nil {
		if err == gorm.ErrRecordNotFound {
			return errors.New(errors.CodeShopNotFound, "店铺不存在")
		}
		return errors.Wrap(errors.CodeInternalError, err, "获取店铺失败")
	}

	accounts, err := s.accountStore.GetByShopID(ctx, shop.ID)
	if err != nil {
		return errors.Wrap(errors.CodeInternalError, err, "查询店铺账号失败")
	}

	if len(accounts) > 0 {
		accountIDs := make([]uint, 0, len(accounts))
		for _, account := range accounts {
			accountIDs = append(accountIDs, account.ID)
		}
		if err := s.accountStore.BulkUpdateStatus(ctx, accountIDs, constants.StatusDisabled, currentUserID); err != nil {
			return errors.Wrap(errors.CodeInternalError, err, "禁用店铺账号失败")
		}
	}

	if err := s.shopStore.Delete(ctx, id); err != nil {
		return errors.Wrap(errors.CodeInternalError, err, "删除店铺失败")
	}

	return nil
}

// GetSubordinateShopIDs 获取下级店铺 ID 列表（包含自己）
func (s *Service) GetSubordinateShopIDs(ctx context.Context, shopID uint) ([]uint, error) {
	return s.shopStore.GetSubordinateShopIDs(ctx, shopID)
}
