package services

import (
	"errors"
	"nearle/models"
	"nearle/repositories"
	"net/http"
)

type TenantService interface {
	SearchTenant(status, keyword string) ([]models.Tenantinfo, error)
	GetAllTenants(pageno, pagesize, aid int, status, tenanttype, keyword string) ([]models.Tenantinfo, error)
	GetTenantLocations(tid int) ([]models.Tenantlocations, error)
	GetTenantSlot() (models.Tenantslot, error)
	CreateTenantCustomer(req models.CreateTenantCustomerRequest) (*models.Tenantcustomer, error)
	GetCustomerTenants(customerID int, categoryID int, tenantFlag int) (*models.CustomerTenantResponse, error)
	GetTenantPricing(tid, aid int) (models.Tenantpricing, error)
	UpdateLocation(input models.Tenantlocations) error
	CreateLocation(data models.Tenantlocations) error
	DeleteLocation(locationid int, tenantid int) error
	GetStaffs(tid int) ([]models.StaffInfo, error)
	CreateStaff(user models.User) error
	UpdateStaff(user models.User) error
	CreateTenantLocation(data models.Tenantlocations) map[string]interface{}
	UpdateTenantLocation(data models.Tenantlocations) map[string]interface{}
	CreateTenantUser(data models.Tenants) (models.UserInfo, error)
	GetTenantByID(tid int, locationid int, userid int) (models.Tenantinfo, error)
	GetTenantByKeyword(keyword string) ([]models.TenantSearch, error)
}

type tenantService struct {
	repo repositories.TenantRepository
}

func NewTenantService(repo repositories.TenantRepository) TenantService {
	return &tenantService{repo: repo}
}

func (s *tenantService) SearchTenant(status, keyword string) ([]models.Tenantinfo, error) {
	return s.repo.SearchTenant(status, keyword)
}

func (s *tenantService) GetAllTenants(pageno, pagesize, aid int, status, tenanttype, keyword string) ([]models.Tenantinfo, error) {
	return s.repo.GetAllTenants(pageno, pagesize, aid, status, tenanttype, keyword)
}

func (s *tenantService) GetTenantLocations(tid int) ([]models.Tenantlocations, error) {
	return s.repo.GetTenantLocations(tid)
}

func (s *tenantService) GetTenantSlot() (models.Tenantslot, error) {
	return s.repo.GetTenantSlot()
}

func (s *tenantService) CreateTenantCustomer(req models.CreateTenantCustomerRequest) (*models.Tenantcustomer, error) {
	tenantCustomer := models.Tenantcustomer{
		TenantID:           req.TenantID,
		LocationID:         req.LocationID,
		CustomerID:         req.CustomerID,
		CustomerLocationID: req.CustomerLocationID,
		Status:             req.Status,
	}
	return s.repo.CreateTenantCustomer(tenantCustomer)
}

func (s *tenantService) GetCustomerTenants(customerID int, categoryID int, tenantFlag int) (*models.CustomerTenantResponse, error) {
	details, err := s.repo.GetCustomerTenants(customerID, categoryID, tenantFlag)
	if err != nil {
		return nil, err
	}

	return &models.CustomerTenantResponse{
		Details: details,
	}, nil
}

func (s *tenantService) GetTenantPricing(tid, aid int) (models.Tenantpricing, error) {
	result, err := s.repo.GetTenantPricing(tid, aid)
	if err != nil {
		return models.Tenantpricing{}, err
	}
	return *result, nil
}

func (s *tenantService) UpdateLocation(input models.Tenantlocations) error {
	return s.repo.UpdateLocation(input)
}

func (s *tenantService) CreateLocation(data models.Tenantlocations) error {
	return s.repo.CreateLocation(data)
}

func (s *tenantService) DeleteLocation(locationid int, tenantid int) error {
	return s.repo.DeleteLocation(locationid, tenantid)
}

func (s *tenantService) GetStaffs(tid int) ([]models.StaffInfo, error) {
	return s.repo.GetStaffs(tid)
}

func (s *tenantService) CreateStaff(user models.User) error {
	return s.repo.CreateStaff(user)
}

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

func (s *tenantService) CreateTenantLocation(data models.Tenantlocations) map[string]interface{} {
	created, err := s.repo.CreateTenantLocation(data)
	if err != nil {
		return map[string]interface{}{
			"code":    http.StatusConflict,
			"message": err.Error(),
			"status":  false,
		}
	}

	// "details" carries back the DB-assigned locationid so the frontend can
	// build the store's QR code (tenantid+locationid) immediately after
	// onboarding, instead of having to look the new location up separately.
	return map[string]interface{}{
		"code":    http.StatusCreated,
		"message": "Tenant Location Successfully Created",
		"status":  true,
		"details": created,
	}
}

func (s *tenantService) UpdateTenantLocation(data models.Tenantlocations) map[string]interface{} {
	err := s.repo.UpdateTenantLocation(data)
	if err != nil {
		return map[string]interface{}{
			"status":  false,
			"code":    http.StatusConflict,
			"message": err.Error(),
		}
	}

	return map[string]interface{}{
		"status":  true,
		"code":    http.StatusAccepted,
		"message": "Tenant Location update successful",
	}
}

func (s *tenantService) CreateTenantUser(data models.Tenants) (models.UserInfo, error) {
	// ✅ Check if tenant already exists
	exists := s.repo.CheckTenantByNo(data.Primarycontact)
	if exists != 0 {
		return models.UserInfo{}, errors.New("Tenant Already Exists")
	}

	// ✅ Create Tenant User
	status, err := s.repo.CreateTenantUser(data)
	if err != nil || !status {
		return models.UserInfo{}, err
	}

	// ✅ Get user details by contact number
	result := s.repo.GetUserByNo(data.Primarycontact)
	return result, nil
}

func (s *tenantService) GetTenantByID(tid int, locationid int, userid int) (models.Tenantinfo, error) {
	return s.repo.GetTenantByID(tid, locationid, userid)
}

func (s *tenantService) GetTenantByKeyword(keyword string) ([]models.TenantSearch, error) {
	return s.repo.GetTenantByKeyword(keyword)
}
