package services

import (
	"errors"
	"nearle/models"
	"nearle/repositories"
	"strings"

	"github.com/gofiber/fiber"
)

type UserService interface {
	GetAllUsers(roleID, tenantID, pageno, pagesize int, keyword string) ([]models.UserInfo, error)
	GetUserByID(uid int) (models.UserInfo, error)
	Login(user models.User) (models.UserInfo, error)
	TenantLogin(user models.User) (models.TenantUserInfo, error)
	UpdateStaff(user models.User) error
	AppLogin(user models.User) (models.TenantUserInfo, fiber.Map, error)
	CreateUser(user models.User) (models.UserInfo, error)
	TenantWebLogin(user models.User) (models.TenantUserInfo, map[string]interface{})
	DeleteUser(userid int) error
}

type userService struct {
	repo repositories.UserRepository
}

func NewUserService(repo repositories.UserRepository) UserService {
	return &userService{repo: repo}
}

func (s *userService) GetAllUsers(roleID, tenantID, pageno, pagesize int, keyword string) ([]models.UserInfo, error) {
	return s.repo.GetAllUsers(roleID, tenantID, pageno, pagesize, keyword)
}

func (s *userService) GetUserByID(uid int) (models.UserInfo, error) {
	return s.repo.GetUserByID(uid)
}

func (s *userService) Login(user models.User) (models.UserInfo, error) {
	return s.repo.Login(user)
}

func (s *userService) TenantLogin(user models.User) (models.TenantUserInfo, error) {
	uid, err := s.repo.FindUserID(user.Authname, user.Contactno, user.Configid)
	if err != nil {
		return models.TenantUserInfo{}, err
	}

	if uid == 0 {
		return models.TenantUserInfo{}, errors.New("user not found")
	}

	return s.repo.GetTenantUserByID(uid)
}

func (s *userService) UpdateStaff(user models.User) error {
	return s.repo.UpdateStaff(user)
}

func (s *userService) AppLogin(user models.User) (models.TenantUserInfo, fiber.Map, error) {
	var uid int
	var status, dbPassword string

	// Get user by authname or contactno
	if user.Authname != "" {
		uid, dbPassword, status = s.repo.GetUserByAuthname(user.Authname, user.Configid)
	} else if user.Contactno != "" {
		uid, dbPassword, status = s.repo.GetUserByContactNo(user.Contactno, user.Configid)
	} else {
		resp := fiber.Map{
			"code":    400,
			"status":  false,
			"message": "authname or contactno required",
		}
		return models.TenantUserInfo{}, resp, errors.New("missing authname or contactno")
	}

	// Invalid user
	if uid == 0 {
		resp := fiber.Map{
			"status":     false,
			"code":       409,
			"message":    "Invalid Email",
			"tenantform": true,
		}
		return models.TenantUserInfo{}, resp, errors.New("invalid user")
	}

	// Inactive account
	if strings.EqualFold(status, "InActive") {
		resp := fiber.Map{
			"status":  false,
			"code":    403,
			"message": "Inactive Account. Contact admin.",
		}
		return models.TenantUserInfo{}, resp, errors.New("inactive account")
	}

	// No password set
	if strings.TrimSpace(dbPassword) == "" {
		resp := fiber.Map{
			"status":     true,
			"code":       409,
			"message":    "Please setup a password.",
			"tenantform": true,
			"details": fiber.Map{
				"userid": uid,
				"setup":  true,
			},
		}
		return models.TenantUserInfo{}, resp, nil
	}

	// Empty request password
	if strings.TrimSpace(user.Password) == "" {
		resp := fiber.Map{
			"status":     true,
			"code":       401,
			"message":    "Password is required",
			"tenantform": true,
		}
		return models.TenantUserInfo{}, resp, nil
	}

	// Incorrect password
	if user.Password != dbPassword {
		resp := fiber.Map{
			"status":     false,
			"code":       401,
			"message":    "Incorrect password",
			"tenantform": true,
		}
		return models.TenantUserInfo{}, resp, errors.New("incorrect password")
	}

	// Update FCM token
	if user.Userfcmtoken != "" {
		_ = s.repo.UpdateFCMToken(uid, user.Userfcmtoken)
	}

	

	// ✅ Fetch tenant user info
	info := s.repo.GetTenantUserById(uid)

	// ✅ Check if assigned store is inactive
	if info.Locationid > 0 {
		storeStatus := s.repo.GetLocationStatus(info.Locationid)
		if strings.EqualFold(storeStatus, "InActive") {
			resp := fiber.Map{
				"status":  false,
				"code":    403,
				"message": "Assigned store is inactive. Contact admin.",
			}
			return models.TenantUserInfo{}, resp, errors.New("inactive store")
		}
	}

	// ✅ Return success response
	resp := fiber.Map{
		"status":  true,
		"code":    200,
		"message": "Login successful",
		"details": info,
	}

	return info, resp, nil
}

func (s *userService) CreateUser(user models.User) (models.UserInfo, error) {
	// Call repository to create user
	userid, err := s.repo.CreateUser(user)
	if err != nil {
		return models.UserInfo{}, err
	}

	// Get user info by id
	info, err := s.repo.GetUserById(userid)
	if err != nil {
		return models.UserInfo{}, err
	}

	return info, nil
}


func (s *userService) TenantWebLogin(user models.User) (models.TenantUserInfo, map[string]interface{}) {
	tenantFormExists := true

	uid, dbPassword, status, roleid := 0, "", "", 0

	// Step 1: Login by authname or contactno
	if user.Authname != "" {
		uid, dbPassword, status, roleid = s.repo.GetUserLogin("authname", user.Authname, user.Configid)
	} else if user.Contactno != "" {
		uid, dbPassword, status, roleid = s.repo.GetUserLogin("contactno", user.Contactno, user.Configid)
	} else {
		return models.TenantUserInfo{}, map[string]interface{}{
			"status":  true,
			"code":    400,
			"message": "authname or contactno required",
		}
	}

	// Step 2: Validate user
	if uid == 0 {
		return models.TenantUserInfo{}, map[string]interface{}{
			"status":     false,
			"code":       409,
			"message":    "Invalid Email",
			"tenantform": tenantFormExists,
		}
	}

	if strings.EqualFold(status, "InActive") {
		return models.TenantUserInfo{}, map[string]interface{}{
			"status":  false,
			"code":    403,
			"message": "Inactive Account. Contact admin.",
		}
	}

	if user.Roleid != roleid {
		return models.TenantUserInfo{}, map[string]interface{}{
			"status":  false,
			"code":    403,
			"message": "Unauthorized email.",
		}
	}

	// Step 3: Password checks
	if strings.TrimSpace(dbPassword) == "" {
		return models.TenantUserInfo{}, map[string]interface{}{
			"status":     true,
			"code":       409,
			"message":    "Please setup a password.",
			"tenantform": tenantFormExists,
			"details": map[string]interface{}{
				"userid": uid,
				"setup":  true,
			},
		}
	}

	if strings.TrimSpace(user.Password) == "" {
		return models.TenantUserInfo{}, map[string]interface{}{
			"status":     true,
			"code":       401,
			"message":    "Password is required",
			"tenantform": tenantFormExists,
		}
	}

	if user.Password != dbPassword {
		return models.TenantUserInfo{}, map[string]interface{}{
			"status":     false,
			"code":       401,
			"message":    "Incorrect password",
			"tenantform": tenantFormExists,
		}
	}

	// Step 4: Update FCM if provided
	if user.Userfcmtoken != "" {
		_ = s.repo.UpdateUserFcmToken(uid, user.Userfcmtoken)
	}

	// Step 5: Get full tenant info
	info := s.repo.GetTenantUserById(uid)

	// Step 6: Check if assigned store is inactive
	if info.Locationid > 0 {
		storeStatus := s.repo.GetLocationStatus(info.Locationid)
		if strings.EqualFold(storeStatus, "InActive") {
			return models.TenantUserInfo{}, map[string]interface{}{
				"status":  false,
				"code":    403,
				"message": "Assigned store is inactive. Contact admin.",
			}
		}
	}

	return info, map[string]interface{}{
		"status":  true,
		"code":    200,
		"message": "Login successful",
	}
}

func (s *userService) DeleteUser(userid int) error {
	return s.repo.DeleteUser(userid)
}


