package controllers

import (
	"nearle/models"
	"nearle/services"
	"net/http"
	"strconv"
	"time"

	"github.com/gofiber/fiber/v2"
)

type CustomerController struct {
	customerService services.CustomerService
}

func NewCustomerController(customerService services.CustomerService) *CustomerController {
	return &CustomerController{customerService: customerService}
}

func (ctl *CustomerController) GetCustomer(c *fiber.Ctx) error {
	cid, _ := strconv.Atoi(c.Query("customerid"))
	cno := c.Query("contactno")

	result, err := ctl.customerService.GetCustomer(cid, cno)
	if err != nil {
		return c.Status(http.StatusInternalServerError).JSON(fiber.Map{
			"code":    500,
			"message": err.Error(),
			"status":  false,
			"details": fiber.Map{},
		})
	}

	return c.Status(http.StatusOK).JSON(fiber.Map{
		"code":    http.StatusOK,
		"message": "Success",
		"status":  true,
		"details": result,
	})
}

func (ctl *CustomerController) UpdateCustomer(c *fiber.Ctx) error {
	var data models.Customers

	if err := c.BodyParser(&data); err != nil {
		return c.Status(http.StatusBadRequest).JSON(fiber.Map{
			"status":  false,
			"code":    http.StatusBadRequest,
			"message": "Invalid request body",
		})
	}

	result := ctl.customerService.UpdateCustomer(data)

	if !result.Status {
		return c.Status(http.StatusConflict).JSON(fiber.Map{
			"status":  false,
			"code":    http.StatusConflict,
			"message": result.Message,
		})
	}

	return c.Status(http.StatusAccepted).JSON(fiber.Map{
		"status":  true,
		"code":    http.StatusAccepted,
		"message": result.Message,
	})
}

func (ctl *CustomerController) GetCustomerLocations(c *fiber.Ctx) error {
	cid, err := strconv.Atoi(c.Query("customerid"))
	if err != nil || cid == 0 {
		return c.Status(http.StatusBadRequest).JSON(fiber.Map{
			"code":    http.StatusBadRequest,
			"status":  false,
			"message": "Invalid customerid",
			"details": []interface{}{},
		})
	}

	result := ctl.customerService.GetCustomerLocations(cid)
	return c.Status(result.Code).JSON(result)
}

func (ctl *CustomerController) CreateCustomerLocation(c *fiber.Ctx) error {
	var data models.Customerlocations

	if err := c.BodyParser(&data); err != nil {
		return c.Status(http.StatusBadRequest).JSON(fiber.Map{
			"status":  false,
			"code":    http.StatusBadRequest,
			"message": "Invalid request body",
		})
	}

	id, err := ctl.customerService.CreateCustomerLocation(data)

	if id == -1 {
		// Duplicate address
		return c.Status(http.StatusConflict).JSON(fiber.Map{
			"status":  false,
			"code":    http.StatusConflict,
			"message": "Address already exists",
		})
	}

	if err != nil || id == 0 {
		return c.Status(http.StatusConflict).JSON(fiber.Map{
			"status":  false,
			"code":    http.StatusConflict,
			"message": "Failed",
		})
	}

	result := ctl.customerService.GetCustomerLocations(id)
	return c.Status(result.Code).JSON(result)
}


func (ctl *CustomerController) CreateCustomerRequest(c *fiber.Ctx) error {
	var req models.CustomerRequest

	if err := c.BodyParser(&req); err != nil {
		return c.Status(http.StatusBadRequest).JSON(fiber.Map{
			"code":    http.StatusBadRequest,
			"message": "Invalid request body",
			"status":  false,
		})
	}

	now := time.Now()
	req.Created = now
	req.Updated = now

	createdReq, err := ctl.customerService.CreateCustomerRequest(req)
	if err != nil {
		return c.Status(http.StatusInternalServerError).JSON(fiber.Map{
			"code":    http.StatusInternalServerError,
			"message": "Failed to create customer request",
			"status":  false,
		})
	}

	return c.Status(http.StatusCreated).JSON(fiber.Map{
		"code":    http.StatusCreated,
		"message": "Customer request created successfully",
		"status":  true,
		"data":    createdReq,
	})
}

func (ctl *CustomerController) GetCustomerRequests(c *fiber.Ctx) error {
	customerIDStr := c.Query("customerid")
	pageNoStr := c.Query("pageno", "1")
	pageSizeStr := c.Query("pagesize", "10")

	pageNo, _ := strconv.Atoi(pageNoStr)
	pageSize, _ := strconv.Atoi(pageSizeStr)

	requests, total, err := ctl.customerService.GetCustomerRequests(customerIDStr, pageNo, pageSize)
	if err != nil {
		return c.Status(http.StatusInternalServerError).JSON(fiber.Map{
			"code":    500,
			"message": err.Error(),
			"status":  false,
		})
	}

	return c.Status(http.StatusOK).JSON(fiber.Map{
		"code":    200,
		"message": "Customer requests fetched successfully",
		"status":  true,
		"data":    requests,
		"total":   total,
	})
}

func (ctl *CustomerController) GetTenantCustomers(c *fiber.Ctx) error {
	tid, _ := strconv.Atoi(c.Query("tenantid"))
	lid, _ := strconv.Atoi(c.Query("locationid"))
	pageno, _ := strconv.Atoi(c.Query("pageno"))
	pagesize, _ := strconv.Atoi(c.Query("pagesize"))
	keyword := c.Query("keyword")

	result := ctl.customerService.GetTenantCustomers(tid, lid, pageno, pagesize, keyword)

	return c.JSON(fiber.Map{
		"code":    http.StatusOK,
		"message": "Success",
		"status":  true,
		"details": result,
	})
}

func (ctl *CustomerController) SearchCustomer(c *fiber.Ctx) error {
	keyword := c.Query("keyword")
	tid, _ := strconv.Atoi(c.Query("tenantid"))

	result := ctl.customerService.SearchCustomer(keyword, tid)

	return c.JSON(fiber.Map{
		"code":    http.StatusOK,
		"message": "Success",
		"status":  true,
		"details": result,
	})
}

func (ctl *CustomerController) CreateCustomer(c *fiber.Ctx) error {
	var data models.Customers

	if err := c.BodyParser(&data); err != nil {
		return err
	}

	result, err := ctl.customerService.CreateCustomer(data)
	if err != nil {
		return c.JSON(fiber.Map{
			"status":  false,
			"code":    http.StatusConflict,
			"message": err.Error(),
		})
	}

	return c.JSON(fiber.Map{
		"status":  true,
		"code":    http.StatusCreated,
		"message": "Successful",
		"details": result,
	})
}

func (ctl *CustomerController) CustomerLogin(c *fiber.Ctx) error {
	var body struct {
		Contactno string `json:"contactno"`
	}

	if err := c.BodyParser(&body); err != nil {
		return c.JSON(fiber.Map{
			"code":    http.StatusBadRequest,
			"status":  false,
			"message": "Invalid request",
			"error":   err.Error(),
		})
	}

	customer, err := ctl.customerService.LoginCustomer(body.Contactno)
	if err != nil {
		return c.Status(http.StatusInternalServerError).JSON(fiber.Map{
			"status":  false,
			"message": "Failed to login",
			"error":   err.Error(),
		})
	}

	if customer == nil {
		return c.JSON(fiber.Map{
			"code":    http.StatusConflict,
			"status":  false,
			"message": "Account not found",
		})
	}

	return c.JSON(fiber.Map{
		"code":    http.StatusOK,
		"status":  true,
		"message": "Success",
		"details": customer,
	})
}
