package controllers

import (
	"fmt"
	"log"
	"nearle/models"
	"nearle/services"
	"net/http"
	"strconv"
	"strings"

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

type TenantController struct {
	tenantService services.TenantService
}

func NewTenantController(tenantService services.TenantService) *TenantController {
	return &TenantController{tenantService: tenantService}
}

func (ctl *TenantController) SearchTenant(c *fiber.Ctx) error {
	status := c.Query("status")
	searchStr := c.Query("keyword")

	data, err := ctl.tenantService.SearchTenant(status, searchStr)
	if err != nil {
		return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
			"code":    http.StatusInternalServerError,
			"message": fmt.Sprintf("Error searching tenants: %v", err),
			"status":  false,
		})
	}

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

func (ctl *TenantController) GetAllTenants(c *fiber.Ctx) error {
	pageno, _ := strconv.Atoi(c.Query("pageno"))
	pagesize, _ := strconv.Atoi(c.Query("pagesize"))
	status := c.Query("status")
	aid, _ := strconv.Atoi(c.Query("applocationid"))
	tenanttype := c.Query("tenanttype")
	keyword := c.Query("keyword")

	details, err := ctl.tenantService.GetAllTenants(pageno, pagesize, aid, status, tenanttype, keyword)
	if err != nil {
		return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
			"code":    http.StatusInternalServerError,
			"message": fmt.Sprintf("Error getting all tenants: %v", err),
			"status":  false,
		})
	}

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

func (ctl *TenantController) GetTenantLocations(c *fiber.Ctx) error {
	tidStr := c.Query("tenantid")
	if tidStr == "" {
		tidStr = c.Query("tenantId")
	}
	if tidStr == "" {
		tidStr = c.Query("tenantID")
	}
	if tidStr == "" {
		tidStr = c.Query("tenant_id")
	}
	tid, _ := strconv.Atoi(strings.TrimSpace(tidStr))

	data, err := ctl.tenantService.GetTenantLocations(tid)
	if err != nil {
		return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
			"code":    http.StatusInternalServerError,
			"message": fmt.Sprintf("Error getting tenant locations: %v", err),
			"status":  false,
		})
	}

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

func (ctl *TenantController) GetTenantSlot(c *fiber.Ctx) error {

	data, err := ctl.tenantService.GetTenantSlot()

	if err != nil {
		return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
			"code":    http.StatusInternalServerError,
			"message": fmt.Sprintf("Error getting tenant slots: %v", err),
			"status":  false,
		})
	}

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

func (ctl *TenantController) CreateTenantCustomer(c *fiber.Ctx) error {
	var req models.CreateTenantCustomerRequest

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

	tenantCustomer, err := ctl.tenantService.CreateTenantCustomer(req)
	if err != nil {
		if strings.Contains(err.Error(), "already exists for this location") {
			return c.JSON(fiber.Map{
				"code":    409,
				"status":  false,
				"message": "Customer already assigned to this location",
				"data":    fiber.Map{},
			})
		}

		log.Println("Error inserting tenant customer:", err)
		return c.JSON(fiber.Map{
			"code":    500,
			"status":  false,
			"message": "Failed to create tenant customer",
			"data":    fiber.Map{},
		})
	}

	return c.Status(http.StatusOK).JSON(fiber.Map{
		"code":    200,
		"status":  true,
		"message": "Tenant customer created successfully",
		"data":    tenantCustomer,
	})
}

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

	categoryID, _ := strconv.Atoi(c.Query("categoryid"))
	tenantFlag, _ := strconv.Atoi(c.Query("tenant")) // 0 = all tenants, 1 = tenants with orders

	data, err := ctl.tenantService.GetCustomerTenants(customerID, categoryID, tenantFlag)
	if err != nil {
		return c.Status(http.StatusInternalServerError).JSON(fiber.Map{
			"code":    500,
			"message": err.Error(),
			"status":  false,
			"details": []interface{}{},
		})
	}

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

func (ctl *TenantController) GetTenantPricing(c *fiber.Ctx) error {
	tid, _ := strconv.Atoi(c.Query("tenantid"))
	aid, _ := strconv.Atoi(c.Query("applocationid"))

	data, err := ctl.tenantService.GetTenantPricing(tid, aid)
	if err != nil {
		return c.JSON(fiber.Map{
			"code":    http.StatusInternalServerError,
			"message": err.Error(),
			"status":  false,
		})
	}

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

func (ctl *TenantController) UpdateLocation(c *fiber.Ctx) error {
	var data models.Tenantlocations

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

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

	return c.JSON(fiber.Map{
		"status":  true,
		"code":    http.StatusAccepted,
		"message": "Location update successful",
	})
}

func (ctl *TenantController) CreateLocation(c *fiber.Ctx) error {
	var data models.Tenantlocations

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

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

	return c.Status(http.StatusCreated).JSON(fiber.Map{
		"code":    http.StatusCreated,
		"message": "Location Successfully Created",
		"status":  true,
	})
}

func (ctl *TenantController) DeleteLocation(c *fiber.Ctx) error {
	locationid, err := strconv.Atoi(c.Query("locationid"))
	if err != nil {
		return c.Status(http.StatusBadRequest).JSON(fiber.Map{
			"code":    http.StatusBadRequest,
			"message": "Invalid location ID",
			"status":  false,
		})
	}

	tenantid, err := strconv.Atoi(c.Query("tenantid"))
	if err != nil {
		return c.Status(http.StatusBadRequest).JSON(fiber.Map{
			"code":    http.StatusBadRequest,
			"message": "Invalid tenant ID",
			"status":  false,
		})
	}

	if err := ctl.tenantService.DeleteLocation(locationid, tenantid); err != nil {
		return c.Status(http.StatusInternalServerError).JSON(fiber.Map{
			"code":    http.StatusInternalServerError,
			"message": err.Error(),
			"status":  false,
		})
	}

	return c.JSON(fiber.Map{
		"code":    http.StatusOK,
		"message": "Location Successfully Deleted",
		"status":  true,
	})
}

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

	data, err := ctl.tenantService.GetStaffs(tid)
	if err != nil {
		return c.Status(http.StatusInternalServerError).JSON(fiber.Map{
			"code":    http.StatusInternalServerError,
			"message": err.Error(),
			"status":  false,
		})
	}

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

func (ctl *TenantController) CreateStaff(c *fiber.Ctx) error {
	var data models.User

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

	if err := ctl.tenantService.CreateStaff(data); err != nil {
		return c.Status(http.StatusInternalServerError).JSON(fiber.Map{
			"code":    http.StatusConflict,
			"message": err.Error(),
			"status":  false,
		})
	}

	return c.JSON(fiber.Map{
		"code":    http.StatusCreated,
		"message": "Staff created successfully",
		"status":  true,
	})
}

func (ctl *TenantController) UpdateStaff(c *fiber.Ctx) error {
	var data models.User

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

	if err := ctl.tenantService.UpdateStaff(data); err != nil {
		return c.Status(http.StatusConflict).JSON(fiber.Map{
			"status":  false,
			"code":    http.StatusConflict,
			"message": err.Error(),
		})
	}

	return c.JSON(fiber.Map{
		"status":  true,
		"code":    http.StatusAccepted,
		"message": "Staff updated successfully",
	})
}

func (ctl *TenantController) CreateTenantLocation(c *fiber.Ctx) error {
	var data models.Tenantlocations

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

	resp := ctl.tenantService.CreateTenantLocation(data)
	return c.Status(fiber.StatusOK).JSON(resp)
}

func (ctl *TenantController) UpdateTenantLocation(c *fiber.Ctx) error {
	var data models.Tenantlocations

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

	// Call service layer
	resp := ctl.tenantService.UpdateTenantLocation(data)

	// Always return HTTP 200 (as per your API pattern)
	return c.Status(fiber.StatusOK).JSON(resp)
}

func (ctl *TenantController) CreateTenantUser(c *fiber.Ctx) error {
	var data models.Tenants

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

	result, err := ctl.tenantService.CreateTenantUser(data)
	if err != nil {
		if err.Error() == "Tenant Already Exists" {
			return c.Status(http.StatusConflict).JSON(fiber.Map{
				"code":    409,
				"status":  false,
				"message": err.Error(),
			})
		}

		return c.Status(http.StatusInternalServerError).JSON(fiber.Map{
			"code":    500,
			"status":  false,
			"message": err.Error(),
		})
	}

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

func (ctl *TenantController) GetTenantInfo(c *fiber.Ctx) error {
	log.Printf("[DEBUG] GetTenantInfo OriginalURL: %s, Headers: %v", c.OriginalURL(), c.GetReqHeaders())
	
	// Parse tenant ID
	tidStr := c.Query("tenantid")
	if tidStr == "" {
		tidStr = c.Query("tenantId")
	}
	if tidStr == "" {
		tidStr = c.Query("tenantID")
	}
	if tidStr == "" {
		tidStr = c.Query("tenant_id")
	}
	if tidStr == "" {
		tidStr = c.Get("tenantid")
	}
	if tidStr == "" {
		tidStr = c.Get("tenantId")
	}
	if tidStr == "" {
		tidStr = c.Get("tenantID")
	}
	if tidStr == "" {
		tidStr = c.Get("tenant_id")
	}
	tid, _ := strconv.Atoi(strings.TrimSpace(tidStr))

	// Parse location ID
	lidStr := c.Query("locationid")
	if lidStr == "" {
		lidStr = c.Query("locationId")
	}
	if lidStr == "" {
		lidStr = c.Query("locationID")
	}
	if lidStr == "" {
		lidStr = c.Query("location_id")
	}
	if lidStr == "" {
		lidStr = c.Get("locationid")
	}
	if lidStr == "" {
		lidStr = c.Get("locationId")
	}
	if lidStr == "" {
		lidStr = c.Get("locationID")
	}
	if lidStr == "" {
		lidStr = c.Get("location_id")
	}
	locationid, _ := strconv.Atoi(strings.TrimSpace(lidStr))

	// Parse user ID
	uidStr := c.Query("userid")
	if uidStr == "" {
		uidStr = c.Query("userId")
	}
	if uidStr == "" {
		uidStr = c.Query("userID")
	}
	if uidStr == "" {
		uidStr = c.Query("user_id")
	}
	if uidStr == "" {
		uidStr = c.Query("appuserid")
	}
	if uidStr == "" {
		uidStr = c.Query("appuserId")
	}
	if uidStr == "" {
		uidStr = c.Query("appuserID")
	}
	if uidStr == "" {
		uidStr = c.Query("appuser_id")
	}
	if uidStr == "" {
		uidStr = c.Get("userid")
	}
	if uidStr == "" {
		uidStr = c.Get("userId")
	}
	if uidStr == "" {
		uidStr = c.Get("userID")
	}
	if uidStr == "" {
		uidStr = c.Get("user_id")
	}
	if uidStr == "" {
		uidStr = c.Get("appuserid")
	}
	if uidStr == "" {
		uidStr = c.Get("appuserId")
	}
	if uidStr == "" {
		uidStr = c.Get("appuserID")
	}
	if uidStr == "" {
		uidStr = c.Get("appuser_id")
	}
	userid, _ := strconv.Atoi(strings.TrimSpace(uidStr))

	data, err := ctl.tenantService.GetTenantByID(tid, locationid, userid)
	if err != nil {
		return c.Status(http.StatusInternalServerError).JSON(fiber.Map{
			"code":    http.StatusInternalServerError,
			"message": "Error fetching tenant info",
			"status":  false,
		})
	}

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

func (ctl *TenantController) GetTenantByKeyword(c *fiber.Ctx) error {
	keyword := c.Query("keyword")

	data, err := ctl.tenantService.GetTenantByKeyword(keyword)
	if err != nil {
		return c.Status(http.StatusInternalServerError).JSON(fiber.Map{
			"code":    500,
			"message": "Error searching tenants by keyword",
			"status":  false,
		})
	}

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