package services

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

type CustomerService interface {
	GetCustomer(cid int, cno string) (*models.CustomerInfo, error)
	UpdateCustomer(input models.Customers) models.Result
	GetCustomerLocations(cid int) models.CustomerLocationResult
	CreateCustomerLocation(input models.Customerlocations) (int, error)
	CreateCustomerRequest(req models.CustomerRequest) (models.CustomerRequest, error)
	GetCustomerRequests(customerIDStr string, pageNo, pageSize int) ([]models.CustomerRequest, int64, error)
	GetTenantCustomers(tid, lid, pageno, pagesize int, keyword string) []models.CustomerInfo
	SearchCustomer(keyword string, tid int) []models.CustomerInfo
	CreateCustomer(input models.Customers) (models.CustomerInfo, error)
	LoginCustomer(contactNo string) (*models.Customers, error)
}

type customerService struct {
	repo repositories.CustomerRepository
}

func NewCustomerService(repo repositories.CustomerRepository) CustomerService {
	return &customerService{repo: repo}
}

func (s *customerService) GetCustomer(cid int, cno string) (*models.CustomerInfo, error) {
	return s.repo.GetCustomer(cid, cno)
}

func (s *customerService) UpdateCustomer(input models.Customers) models.Result {
	err := s.repo.UpdateCustomer(input)
	if err != nil {
		return models.Result{
			Code:    http.StatusConflict,
			Status:  false,
			Message: "Update Customer Failed",
		}
	}

	return models.Result{
		Code:    http.StatusAccepted,
		Status:  true,
		Message: "Customer update successful",
	}
}

func (s *customerService) CreateCustomerLocation(input models.Customerlocations) (int, error) {
	return s.repo.CreateCustomerLocation(input)
}

func (s *customerService) GetCustomerLocations(cid int) models.CustomerLocationResult {
	data, err := s.repo.GetCustomerLocations(cid)
	if err != nil {
		return models.CustomerLocationResult{
			Code:    http.StatusInternalServerError,
			Status:  false,
			Message: "Failed to fetch customer locations",
			Details: []models.Customerlocations{},
		}
	}

	return models.CustomerLocationResult{
		Code:    http.StatusOK,
		Status:  true,
		Message: "Successful",
		Details: data,
	}
}

func (s *customerService) CreateCustomerRequest(req models.CustomerRequest) (models.CustomerRequest, error) {
	err := s.repo.CreateCustomerRequest(&req)
	if err != nil {
		return models.CustomerRequest{}, err
	}
	return req, nil
}

func (s *customerService) GetCustomerRequests(customerIDStr string, pageNo, pageSize int) ([]models.CustomerRequest, int64, error) {
	if pageNo < 1 {
		pageNo = 1
	}
	if pageSize < 1 {
		pageSize = 10
	}

	var customerID int
	var err error
	if customerIDStr != "" {
		customerID, err = strconv.Atoi(customerIDStr)
		if err != nil {
			return nil, 0, errors.New("invalid customerid")
		}
	}

	return s.repo.GetCustomerRequests(customerID, pageNo, pageSize)
}

func (s *customerService) GetTenantCustomers(tid, lid, pageno, pagesize int, keyword string) []models.CustomerInfo {
	return s.repo.GetTenantCustomers(tid, lid, pageno, pagesize, keyword)
}

func (s *customerService) SearchCustomer(keyword string, tid int) []models.CustomerInfo {
	return s.repo.SearchCustomer(keyword, tid)
}

func (s *customerService) CreateCustomer(input models.Customers) (models.CustomerInfo, error) {

	cid := s.repo.CheckCustomer(input.Contactno)
	if cid != 0 {
		input.Customerid = cid

		tcid := s.repo.CheckTenantCustomer(input.Customerid, input.Tenantid)
		if tcid != 0 {
			return models.CustomerInfo{}, errors.New("Customer Already available")
		}

		s.repo.CreateTenantCustomer(input)
	} else {

		cid = s.repo.CreateCustomer(input)
	}

	result, err := s.repo.GetCustomer(cid, "")
	if err != nil {
		return models.CustomerInfo{}, err
	}
	return *result, nil

}

func (s *customerService) LoginCustomer(contactNo string) (*models.Customers, error) {
	customer, err := s.repo.GetCustomerByContactNo(contactNo)
	if err != nil {
		return nil, err
	}

	if customer.Customerid == 0 {
		return nil, nil // handle "not found" in controller
	}

	return customer, nil
}
