package customer

import (
	"strconv"
	"tm/internal/user"
	"tm/pkg/authorization"
	"tm/pkg/logger"
	"tm/pkg/response"

	"github.com/labstack/echo/v4"
)

// Handler handles HTTP requests for customer operations
type Handler struct {
	service     Service
	authService authorization.AuthorizationService
	userHandler *user.Handler
	logger      logger.Logger
}

// NewHandler creates a new customer handler
func NewHandler(service Service, userHandler *user.Handler, authService authorization.AuthorizationService, logger logger.Logger) *Handler {
	return &Handler{
		service:     service,
		authService: authService,
		userHandler: userHandler,
		logger:      logger,
	}
}

// CreateCustomer creates a new customer (Web Panel)
// @Summary Create a new customer
// @Description Create a new customer with comprehensive information including personal details, company information, address, and business details. This endpoint is used by the web panel for full customer registration.
// @Tags Admin-Customers
// @Accept json
// @Produce json
// @Param customer body CreateCustomerForm true "Customer information including type (individual|company|government), personal details, company info, address, and business details"
// @Success 201 {object} response.APIResponse{data=CustomerResponse} "Customer created successfully"
// @Failure 400 {object} response.APIResponse "Bad request - Invalid input data"
// @Failure 409 {object} response.APIResponse "Conflict - Customer with this email/company already exists"
// @Failure 422 {object} response.APIResponse "Validation error - Invalid request data"
// @Failure 500 {object} response.APIResponse "Internal server error"
// @Security BearerAuth
// @Router /admin/v1/customers [post]
func (h *Handler) CreateCustomer(c echo.Context) error {
	form, err := response.Parse[CreateCustomerForm](c)
	if err != nil {
		return response.ValidationError(c, "Invalid request data", err.Error())
	}

	// Get user ID from JWT token context
	createdBy, err := user.GetUserIDFromContext(c)
	if err != nil {
		return response.Unauthorized(c, "User not authenticated")
	}

	customer, err := h.service.CreateCustomer(c.Request().Context(), form, &createdBy)
	if err != nil {
		if err.Error() == "customer with this email already exists" ||
			err.Error() == "company with this name already exists" ||
			err.Error() == "company with this registration number already exists" ||
			err.Error() == "company with this tax ID already exists" {
			return response.Conflict(c, err.Error())
		}
		return response.InternalServerError(c, "Failed to create customer")
	}

	return response.Created(c, customer.ToResponse(), "Customer created successfully")
}

// GetCustomerByID retrieves a customer by ID (Web Panel)
// @Summary Get customer by ID
// @Description Retrieve detailed customer information by customer ID
// @Tags Admin-Customers
// @Accept json
// @Produce json
// @Param id path string true "Customer ID"
// @Success 200 {object} response.APIResponse{data=CustomerResponse} "Customer retrieved successfully"
// @Failure 400 {object} response.APIResponse "Bad request - Invalid customer ID"
// @Failure 404 {object} response.APIResponse "Not found - Customer not found"
// @Failure 500 {object} response.APIResponse "Internal server error"
// @Security BearerAuth
// @Router /admin/v1/customers/{id} [get]
func (h *Handler) GetCustomerByID(c echo.Context) error {
	idStr := c.Param("id")

	customer, err := h.service.GetCustomerByIDWithCompanies(c.Request().Context(), idStr)
	if err != nil {
		if err.Error() == "customer not found" {
			return response.NotFound(c, "Customer not found")
		}
		return response.InternalServerError(c, "Failed to get customer")
	}

	return response.Success(c, customer, "Customer retrieved successfully")
}

// UpdateCustomer updates a customer (Web Panel)
// @Summary Update customer information
// @Description Update customer information including personal details, company information, address, and business details
// @Tags Admin-Customers
// @Accept json
// @Produce json
// @Param id path string true "Customer ID"
// @Param customer body UpdateCustomerForm true "Updated customer information"
// @Success 200 {object} response.APIResponse{data=CustomerResponse} "Customer updated successfully"
// @Failure 400 {object} response.APIResponse "Bad request - Invalid input data"
// @Failure 404 {object} response.APIResponse "Not found - Customer not found"
// @Failure 409 {object} response.APIResponse "Conflict - Customer with this email/company already exists"
// @Failure 422 {object} response.APIResponse "Validation error - Invalid request data"
// @Failure 500 {object} response.APIResponse "Internal server error"
// @Security BearerAuth
// @Router /admin/v1/customers/{id} [put]
func (h *Handler) UpdateCustomer(c echo.Context) error {
	idStr := c.Param("id")
	form, err := response.Parse[UpdateCustomerForm](c)
	if err != nil {
		return response.ValidationError(c, "Invalid request data", err.Error())
	}

	// Get user ID from JWT token context
	updatedBy, err := user.GetUserIDFromContext(c)
	if err != nil {
		return response.Unauthorized(c, "User not authenticated")
	}

	customer, err := h.service.UpdateCustomer(c.Request().Context(), idStr, form, &updatedBy)
	if err != nil {
		if err.Error() == "customer not found" {
			return response.NotFound(c, "Customer not found")
		}
		if err.Error() == "customer with this email already exists" ||
			err.Error() == "company with this name already exists" ||
			err.Error() == "company with this registration number already exists" ||
			err.Error() == "company with this tax ID already exists" {
			return response.Conflict(c, err.Error())
		}
		return response.InternalServerError(c, "Failed to update customer")
	}

	return response.Success(c, customer.ToResponse(), "Customer updated successfully")
}

// DeleteCustomer deletes a customer (Web Panel)
// @Summary Delete customer
// @Description Soft delete a customer by setting status to inactive
// @Tags Admin-Customers
// @Accept json
// @Produce json
// @Param id path string true "Customer ID"
// @Success 200 {object} response.APIResponse "Customer deleted successfully"
// @Failure 400 {object} response.APIResponse "Bad request - Invalid customer ID"
// @Failure 404 {object} response.APIResponse "Not found - Customer not found"
// @Failure 500 {object} response.APIResponse "Internal server error"
// @Security BearerAuth
// @Router /admin/v1/customers/{id} [delete]
func (h *Handler) DeleteCustomer(c echo.Context) error {
	idStr := c.Param("id")

	// Get user ID from JWT token context
	deletedBy, err := user.GetUserIDFromContext(c)
	if err != nil {
		return response.Unauthorized(c, "User not authenticated")
	}

	err = h.service.DeleteCustomer(c.Request().Context(), idStr, &deletedBy)
	if err != nil {
		if err.Error() == "customer not found" {
			return response.NotFound(c, "Customer not found")
		}
		return response.InternalServerError(c, "Failed to delete customer")
	}

	return response.Success(c, map[string]interface{}{
		"message": "Customer deleted successfully",
	}, "Customer deleted successfully")
}

// ListCustomers lists customers with filters and pagination
// @Summary List customers with filters and pagination
// @Description Retrieve a paginated list of customers with advanced filtering options including search, type, status, company, industry, verification status, and compliance status. Supports sorting and pagination.
// @Tags Admin-Customers
// @Accept json
// @Produce json
// @Param search query string false "Search term to filter customers by name, email, or company name"
// @Param type query string false "Filter by customer type" Enums(individual, company, government)
// @Param status query string false "Filter by customer status" Enums(active, inactive, suspended, pending)
// @Param company_id query string false "Filter by company ID" format(uuid)
// @Param industry query string false "Filter by industry"
// @Param is_verified query boolean false "Filter by verification status"
// @Param is_compliant query boolean false "Filter by compliance status"
// @Param language query string false "Filter by preferred language"
// @Param currency query string false "Filter by preferred currency"
// @Param limit query integer false "Number of customers per page (1-100)" minimum(1) maximum(100) default(20)
// @Param offset query integer false "Number of customers to skip for pagination" minimum(0) default(0)
// @Param sort_by query string false "Field to sort by" Enums(email, company_name, created_at, updated_at, status) default(created_at)
// @Param sort_order query string false "Sort order" Enums(asc, desc) default(desc)
// @Success 200 {object} response.APIResponse{data=CustomerListResponse} "Customers retrieved successfully"
// @Failure 400 {object} response.APIResponse "Bad request - Invalid query parameters"
// @Failure 422 {object} response.APIResponse "Validation error - Invalid query parameters"
// @Failure 500 {object} response.APIResponse "Internal server error"
// @Security BearerAuth
// @Router /admin/v1/customers [get]
func (h *Handler) ListCustomers(c echo.Context) error {
	form, err := response.Parse[ListCustomersForm](c)
	if err != nil {
		return response.ValidationError(c, "Invalid request data", err.Error())
	}

	result, err := h.service.ListCustomers(c.Request().Context(), form)
	if err != nil {
		return response.InternalServerError(c, "Failed to list customers")
	}

	return response.Success(c, result, "Customers retrieved successfully")
}

// UpdateCustomerStatus updates customer status (Web Panel)
// @Summary Update customer status
// @Description Update customer account status (active, inactive, suspended, pending)
// @Tags Admin-Customers
// @Accept json
// @Produce json
// @Param id path string true "Customer ID"
// @Param status body UpdateCustomerStatusForm true "New customer status"
// @Success 200 {object} response.APIResponse "Customer status updated successfully"
// @Failure 400 {object} response.APIResponse "Bad request - Invalid input data"
// @Failure 404 {object} response.APIResponse "Not found - Customer not found"
// @Failure 422 {object} response.APIResponse "Validation error - Invalid request data"
// @Failure 500 {object} response.APIResponse "Internal server error"
// @Security BearerAuth
// @Router /admin/v1/customers/{id}/status [patch]
func (h *Handler) UpdateCustomerStatus(c echo.Context) error {
	idStr := c.Param("id")
	form, err := response.Parse[UpdateCustomerStatusForm](c)
	if err != nil {
		return response.ValidationError(c, "Invalid request data", err.Error())
	}

	// Get user ID from JWT token context
	updatedBy, err := user.GetUserIDFromContext(c)
	if err != nil {
		return response.Unauthorized(c, "User not authenticated")
	}

	err = h.service.UpdateCustomerStatus(c.Request().Context(), idStr, form, &updatedBy)
	if err != nil {
		if err.Error() == "customer not found" {
			return response.NotFound(c, "Customer not found")
		}
		return response.InternalServerError(c, "Failed to update customer status")
	}

	return response.Success(c, map[string]interface{}{
		"message": "Customer status updated successfully",
	}, "Customer status updated successfully")
}

// UpdateCustomerVerification updates customer verification status (Web Panel)
// @Summary Update customer verification status
// @Description Update customer verification and compliance status
// @Tags Admin-Customers
// @Accept json
// @Produce json
// @Param id path string true "Customer ID"
// @Param verification body UpdateCustomerVerificationForm true "Verification status update"
// @Success 200 {object} response.APIResponse "Customer verification updated successfully"
// @Failure 400 {object} response.APIResponse "Bad request - Invalid input data"
// @Failure 404 {object} response.APIResponse "Not found - Customer not found"
// @Failure 422 {object} response.APIResponse "Validation error - Invalid request data"
// @Failure 500 {object} response.APIResponse "Internal server error"
// @Security BearerAuth
// @Router /admin/v1/customers/{id}/verification [patch]
func (h *Handler) UpdateCustomerVerification(c echo.Context) error {
	idStr := c.Param("id")
	form, err := response.Parse[UpdateCustomerVerificationForm](c)
	if err != nil {
		return response.ValidationError(c, "Invalid request data", err.Error())
	}

	// Get user ID from JWT token context
	updatedBy, err := user.GetUserIDFromContext(c)
	if err != nil {
		return response.Unauthorized(c, "User not authenticated")
	}

	err = h.service.UpdateCustomerVerification(c.Request().Context(), idStr, form, &updatedBy)
	if err != nil {
		if err.Error() == "customer not found" {
			return response.NotFound(c, "Customer not found")
		}
		return response.InternalServerError(c, "Failed to update customer verification")
	}

	return response.Success(c, map[string]interface{}{
		"message": "Customer verification updated successfully",
	}, "Customer verification updated successfully")
}

// VerifyCustomer verifies a customer (Web Panel)
// @Summary Verify customer
// @Description Mark a customer as verified
// @Tags Admin-Customers
// @Accept json
// @Produce json
// @Param id path string true "Customer ID"
// @Success 200 {object} response.APIResponse "Customer verified successfully"
// @Failure 400 {object} response.APIResponse "Bad request - Invalid customer ID"
// @Failure 404 {object} response.APIResponse "Not found - Customer not found"
// @Failure 500 {object} response.APIResponse "Internal server error"
// @Security BearerAuth
// @Router /admin/v1/customers/{id}/verify [post]
func (h *Handler) VerifyCustomer(c echo.Context) error {
	idStr := c.Param("id")

	// Get user ID from JWT token context
	verifiedBy, err := user.GetUserIDFromContext(c)
	if err != nil {
		return response.Unauthorized(c, "User not authenticated")
	}

	err = h.service.VerifyCustomer(c.Request().Context(), idStr, &verifiedBy)
	if err != nil {
		if err.Error() == "customer not found" {
			return response.NotFound(c, "Customer not found")
		}
		return response.InternalServerError(c, "Failed to verify customer")
	}

	return response.Success(c, map[string]interface{}{
		"message": "Customer verified successfully",
	}, "Customer verified successfully")
}

// SuspendCustomer suspends a customer (Web Panel)
// @Summary Suspend customer
// @Description Suspend a customer account with optional reason
// @Tags Admin-Customers
// @Accept json
// @Produce json
// @Param id path string true "Customer ID"
// @Param suspension body SuspendCustomerForm true "Suspension information"
// @Success 200 {object} response.APIResponse "Customer suspended successfully"
// @Failure 400 {object} response.APIResponse "Bad request - Invalid input data"
// @Failure 404 {object} response.APIResponse "Not found - Customer not found"
// @Failure 422 {object} response.APIResponse "Validation error - Invalid request data"
// @Failure 500 {object} response.APIResponse "Internal server error"
// @Security BearerAuth
// @Router /admin/v1/customers/{id}/suspend [post]
func (h *Handler) SuspendCustomer(c echo.Context) error {
	idStr := c.Param("id")
	form, err := response.Parse[SuspendCustomerForm](c)
	if err != nil {
		return response.ValidationError(c, "Invalid request data", err.Error())
	}

	// Get user ID from JWT token context
	suspendedBy, err := user.GetUserIDFromContext(c)
	if err != nil {
		return response.Unauthorized(c, "User not authenticated")
	}

	err = h.service.SuspendCustomer(c.Request().Context(), idStr, form.Reason, &suspendedBy)
	if err != nil {
		if err.Error() == "customer not found" {
			return response.NotFound(c, "Customer not found")
		}
		return response.InternalServerError(c, "Failed to suspend customer")
	}

	return response.Success(c, map[string]interface{}{
		"message": "Customer suspended successfully",
	}, "Customer suspended successfully")
}

// ActivateCustomer activates a customer (Web Panel)
// @Summary Activate customer
// @Description Activate a suspended customer account
// @Tags Admin-Customers
// @Accept json
// @Produce json
// @Param id path string true "Customer ID"
// @Success 200 {object} response.APIResponse "Customer activated successfully"
// @Failure 400 {object} response.APIResponse "Bad request - Invalid customer ID"
// @Failure 404 {object} response.APIResponse "Not found - Customer not found"
// @Failure 500 {object} response.APIResponse "Internal server error"
// @Security BearerAuth
// @Router /admin/v1/customers/{id}/activate [post]
func (h *Handler) ActivateCustomer(c echo.Context) error {
	idStr := c.Param("id")

	// Get user ID from JWT token context
	activatedBy, err := user.GetUserIDFromContext(c)
	if err != nil {
		return response.Unauthorized(c, "User not authenticated")
	}

	err = h.service.ActivateCustomer(c.Request().Context(), idStr, &activatedBy)
	if err != nil {
		if err.Error() == "customer not found" {
			return response.NotFound(c, "Customer not found")
		}
		return response.InternalServerError(c, "Failed to activate customer")
	}

	return response.Success(c, map[string]interface{}{
		"message": "Customer activated successfully",
	}, "Customer activated successfully")
}

// GetCustomersByCompanyID retrieves customers by company ID (Web Panel)
// @Summary Get customers by company ID
// @Description Retrieve all customers associated with a specific company
// @Tags Admin-Customers
// @Accept json
// @Produce json
// @Param companyId path string true "Company ID"
// @Param limit query int false "Number of customers to return (default: 10, max: 100)"
// @Param offset query int false "Number of customers to skip (default: 0)"
// @Success 200 {object} response.APIResponse{data=[]CustomerResponse} "Customers retrieved successfully"
// @Failure 400 {object} response.APIResponse "Bad request - Invalid company ID"
// @Failure 500 {object} response.APIResponse "Internal server error"
// @Security BearerAuth
// @Router /admin/v1/customers/company/{companyId} [get]
func (h *Handler) GetCustomersByCompanyID(c echo.Context) error {
	companyIDStr := c.Param("companyId")

	// Parse pagination parameters
	limit := 10 // Default limit
	offset := 0 // Default offset

	if limitStr := c.QueryParam("limit"); limitStr != "" {
		if parsedLimit, err := strconv.Atoi(limitStr); err == nil && parsedLimit > 0 && parsedLimit <= 100 {
			limit = parsedLimit
		}
	}

	if offsetStr := c.QueryParam("offset"); offsetStr != "" {
		if parsedOffset, err := strconv.Atoi(offsetStr); err == nil && parsedOffset >= 0 {
			offset = parsedOffset
		}
	}

	customers, total, err := h.service.GetCustomersByCompanyID(c.Request().Context(), companyIDStr, limit, offset)
	if err != nil {
		return response.InternalServerError(c, "Failed to get customers by company")
	}

	// Convert to responses
	var customerResponses []*CustomerResponse
	for _, customer := range customers {
		customerResponses = append(customerResponses, customer.ToResponse())
	}

	return response.Success(c, map[string]interface{}{
		"customers": customerResponses,
		"total":     total,
		"limit":     limit,
		"offset":    offset,
	}, "Customers retrieved successfully")
}

// GetCustomersByType retrieves customers by type
// @Summary Get customers by type
// @Description Retrieve customers filtered by their type (individual, company, or government). Useful for administrative reporting and management.
// @Tags Admin-Customers
// @Accept json
// @Produce json
// @Param type path string true "Customer type" Enums(individual, company, government)
// @Param limit query integer false "Number of customers per page (1-100)" minimum(1) maximum(100) default(20)
// @Param offset query integer false "Number of customers to skip for pagination" minimum(0) default(0)
// @Success 200 {object} response.APIResponse{data=[]CustomerResponse,meta=response.Meta} "Customers retrieved successfully"
// @Failure 400 {object} response.APIResponse "Bad request - Invalid customer type"
// @Failure 500 {object} response.APIResponse "Internal server error"
// @Security BearerAuth
// @Router /admin/v1/customers/type/{type} [get]
func (h *Handler) GetCustomersByType(c echo.Context) error {
	customerTypeStr := c.Param("type")
	customerType := CustomerType(customerTypeStr)

	// Validate customer type
	if customerType != CustomerTypeIndividual && customerType != CustomerTypeCompany && customerType != CustomerTypeGovernment {
		return response.BadRequest(c, "Invalid customer type", "Must be individual, company, or government")
	}

	limit := 20
	if limitStr := c.QueryParam("limit"); limitStr != "" {
		if parsedLimit, err := strconv.Atoi(limitStr); err == nil && parsedLimit > 0 && parsedLimit <= 100 {
			limit = parsedLimit
		}
	}

	offset := 0
	if offsetStr := c.QueryParam("offset"); offsetStr != "" {
		if parsedOffset, err := strconv.Atoi(offsetStr); err == nil && parsedOffset >= 0 {
			offset = parsedOffset
		}
	}

	customers, total, err := h.service.GetCustomersByType(c.Request().Context(), customerType, limit, offset)
	if err != nil {
		return response.InternalServerError(c, "Failed to retrieve customers by type")
	}

	var customerResponses []*CustomerResponse
	for _, customer := range customers {
		customerResponses = append(customerResponses, customer.ToResponse())
	}

	meta := &response.Meta{
		Total:  int(total),
		Limit:  limit,
		Offset: offset,
	}

	return response.SuccessWithMeta(c, customerResponses, meta, "Customers retrieved successfully")
}

// GetCustomersByStatus retrieves customers by status
// @Summary Get customers by status
// @Description Retrieve customers filtered by their account status (active, inactive, suspended, or pending). Useful for administrative monitoring and management.
// @Tags Admin-Customers
// @Accept json
// @Produce json
// @Param status path string true "Customer status" Enums(active, inactive, suspended, pending)
// @Param limit query integer false "Number of customers per page (1-100)" minimum(1) maximum(100) default(20)
// @Param offset query integer false "Number of customers to skip for pagination" minimum(0) default(0)
// @Success 200 {object} response.APIResponse{data=[]CustomerResponse,meta=response.Meta} "Customers retrieved successfully"
// @Failure 400 {object} response.APIResponse "Bad request - Invalid customer status"
// @Failure 500 {object} response.APIResponse "Internal server error"
// @Security BearerAuth
// @Router /admin/v1/customers/status/{status} [get]
func (h *Handler) GetCustomersByStatus(c echo.Context) error {
	statusStr := c.Param("status")
	status := CustomerStatus(statusStr)

	// Validate customer status
	if status != CustomerStatusActive && status != CustomerStatusInactive && status != CustomerStatusSuspended && status != CustomerStatusPending {
		return response.BadRequest(c, "Invalid customer status", "Must be active, inactive, suspended, or pending")
	}

	limit := 20
	if limitStr := c.QueryParam("limit"); limitStr != "" {
		if parsedLimit, err := strconv.Atoi(limitStr); err == nil && parsedLimit > 0 && parsedLimit <= 100 {
			limit = parsedLimit
		}
	}

	offset := 0
	if offsetStr := c.QueryParam("offset"); offsetStr != "" {
		if parsedOffset, err := strconv.Atoi(offsetStr); err == nil && parsedOffset >= 0 {
			offset = parsedOffset
		}
	}

	customers, total, err := h.service.GetCustomersByStatus(c.Request().Context(), status, limit, offset)
	if err != nil {
		return response.InternalServerError(c, "Failed to retrieve customers by status")
	}

	var customerResponses []*CustomerResponse
	for _, customer := range customers {
		customerResponses = append(customerResponses, customer.ToResponse())
	}

	meta := &response.Meta{
		Total:  int(total),
		Limit:  limit,
		Offset: offset,
	}

	return response.SuccessWithMeta(c, customerResponses, meta, "Customers retrieved successfully")
}

// AssignCompaniesToCustomer assigns companies to a customer (Web Panel)
// @Summary Assign companies to a customer
// @Description Assign one or more companies to a specific customer.
// @Tags Admin-Customers
// @Accept json
// @Produce json
// @Param id path string true "Customer ID"
// @Param companies body AssignCompaniesForm true "List of company IDs to assign"
// @Success 200 {object} response.APIResponse "Companies assigned successfully"
// @Failure 400 {object} response.APIResponse "Bad request - Invalid input data"
// @Failure 404 {object} response.APIResponse "Not found - Customer not found"
// @Failure 422 {object} response.APIResponse "Validation error - Invalid request data"
// @Failure 500 {object} response.APIResponse "Internal server error"
// @Security BearerAuth
// @Router /admin/v1/customers/{id}/companies/assign [post]
func (h *Handler) AssignCompaniesToCustomer(c echo.Context) error {
	idStr := c.Param("id")
	form, err := response.Parse[AssignCompaniesForm](c)
	if err != nil {
		return response.ValidationError(c, "Invalid request data", err.Error())
	}

	// Get user ID from JWT token context
	assignedBy, err := user.GetUserIDFromContext(c)
	if err != nil {
		return response.Unauthorized(c, "User not authenticated")
	}

	err = h.service.AssignCompaniesToCustomer(c.Request().Context(), idStr, form.CompanyIDs, &assignedBy)
	if err != nil {
		if err.Error() == "customer not found" {
			return response.NotFound(c, "Customer not found")
		}
		return response.InternalServerError(c, "Failed to assign companies to customer")
	}

	return response.Success(c, map[string]interface{}{
		"message": "Companies assigned successfully",
	}, "Companies assigned successfully")
}

// RemoveCompaniesFromCustomer removes companies from a customer (Web Panel)
// @Summary Remove companies from a customer
// @Description Remove one or more companies from a specific customer.
// @Tags Admin-Customers
// @Accept json
// @Produce json
// @Param id path string true "Customer ID"
// @Param companies body RemoveCompaniesForm true "List of company IDs to remove"
// @Success 200 {object} response.APIResponse "Companies removed successfully"
// @Failure 400 {object} response.APIResponse "Bad request - Invalid input data"
// @Failure 404 {object} response.APIResponse "Not found - Customer not found"
// @Failure 422 {object} response.APIResponse "Validation error - Invalid request data"
// @Failure 500 {object} response.APIResponse "Internal server error"
// @Security BearerAuth
// @Router /admin/v1/customers/{id}/companies/remove [post]
func (h *Handler) RemoveCompaniesFromCustomer(c echo.Context) error {
	idStr := c.Param("id")
	form, err := response.Parse[RemoveCompaniesForm](c)
	if err != nil {
		return response.ValidationError(c, "Invalid request data", err.Error())
	}

	// Get user ID from JWT token context
	removedBy, err := user.GetUserIDFromContext(c)
	if err != nil {
		return response.Unauthorized(c, "User not authenticated")
	}

	err = h.service.RemoveCompaniesFromCustomer(c.Request().Context(), idStr, form.CompanyIDs, &removedBy)
	if err != nil {
		if err.Error() == "customer not found" {
			return response.NotFound(c, "Customer not found")
		}
		return response.InternalServerError(c, "Failed to remove companies from customer")
	}

	return response.Success(c, map[string]interface{}{
		"message": "Companies removed successfully",
	}, "Companies removed successfully")
}

// Login handles customer authentication
// @Summary Customer login
// @Description Authenticate customer with username (email) and password. Returns access token, refresh token, and customer information upon successful authentication.
// @Tags Authorization
// @Accept json
// @Produce json
// @Param login body LoginForm true "Login credentials (username/email and password)"
// @Success 200 {object} response.APIResponse{data=AuthResponse} "Login successful"
// @Failure 400 {object} response.APIResponse "Bad request - Invalid input data"
// @Failure 401 {object} response.APIResponse "Unauthorized - Invalid credentials or inactive account"
// @Failure 422 {object} response.APIResponse "Validation error - Invalid request data"
// @Failure 500 {object} response.APIResponse "Internal server error"
// @Router /api/v1/profile/login [post]
func (h *Handler) Login(c echo.Context) error {
	form, err := response.Parse[LoginForm](c)
	if err != nil {
		return response.ValidationError(c, "Invalid request data", err.Error())
	}

	// Call service
	authResponse, err := h.service.Login(c.Request().Context(), form)
	if err != nil {
		if err.Error() == "invalid credentials" {
			return response.Unauthorized(c, err.Error())
		}
		if err.Error() == "account is not active" {
			return response.Unauthorized(c, err.Error())
		}
		return response.InternalServerError(c, "Failed to authenticate customer")
	}

	return response.Success(c, authResponse, "Login successful")
}

// RefreshToken handles customer token refresh
// @Summary Refresh customer access token
// @Description Refresh access token using a valid refresh token. This allows customers to maintain their session without re-authentication.
// @Tags Authorization
// @Accept json
// @Produce json
// @Param refresh body RefreshTokenForm true "Refresh token for generating new access token"
// @Success 200 {object} response.APIResponse{data=AuthResponse} "Token refreshed successfully"
// @Failure 400 {object} response.APIResponse "Bad request - Invalid refresh token or feature not implemented"
// @Failure 401 {object} response.APIResponse "Unauthorized - Invalid or expired refresh token"
// @Failure 422 {object} response.APIResponse "Validation error - Invalid request data"
// @Failure 500 {object} response.APIResponse "Internal server error"
// @Router /api/v1/profile/refresh-token [post]
func (h *Handler) RefreshToken(c echo.Context) error {
	form, err := response.Parse[RefreshTokenForm](c)
	if err != nil {
		return response.ValidationError(c, "Invalid request data", err.Error())
	}

	// Call service
	authResponse, err := h.service.RefreshToken(c.Request().Context(), form.RefreshToken)
	if err != nil {
		if err.Error() == "token refresh not implemented yet" {
			return response.BadRequest(c, "Token refresh not implemented yet", "")
		}
		return response.InternalServerError(c, "Failed to refresh token")
	}

	return response.Success(c, authResponse, "Token refreshed successfully")
}

// GetProfile retrieves customer profile information (Mobile)
// @Summary Get customer profile
// @Description Retrieve current customer profile information
// @Tags Authorization
// @Accept json
// @Produce json
// @Security BearerAuth
// @Success 200 {object} response.APIResponse{data=CustomerResponse} "Profile retrieved successfully"
// @Failure 401 {object} response.APIResponse "Unauthorized - Invalid or missing token"
// @Failure 404 {object} response.APIResponse "Not found - Customer not found"
// @Failure 500 {object} response.APIResponse "Internal server error"
// @Router /api/v1/profile [get]
func (h *Handler) GetProfile(c echo.Context) error {
	// Extract customer ID from JWT token context
	customerID, err := GetCustomerIDFromContext(c)
	if err != nil {
		return response.Unauthorized(c, "Customer not authenticated")
	}

	resp, err := h.service.GetProfileWithCompanies(c.Request().Context(), customerID)
	if err != nil {
		if err.Error() == "customer not found" {
			return response.NotFound(c, "Customer not found")
		}
		return response.InternalServerError(c, "Failed to get customer profile")
	}

	return response.Success(c, resp, "Profile retrieved successfully")
}

// Logout handles customer logout (Mobile)
// @Summary Customer logout
// @Description Logout customer and invalidate access token
// @Tags Authorization
// @Accept json
// @Produce json
// @Security BearerAuth
// @Success 200 {object} response.APIResponse "Logout successful"
// @Failure 401 {object} response.APIResponse "Unauthorized - Invalid or missing token"
// @Failure 500 {object} response.APIResponse "Internal server error"
// @Router /api/v1/profile/logout [delete]
func (h *Handler) Logout(c echo.Context) error {
	// Extract customer ID from JWT token context
	customerID, err := GetCustomerIDFromContext(c)
	if err != nil {
		return response.Unauthorized(c, "Customer not authenticated")
	}

	// Get access token from context
	accessToken, err := GetAccessTokenFromContext(c)
	if err != nil {
		return response.Unauthorized(c, "Access token not found")
	}

	err = h.service.Logout(c.Request().Context(), customerID, accessToken)
	if err != nil {
		// Don't return error here as the customer should still be logged out
		h.logger.Warn("Failed to invalidate access token during logout", map[string]interface{}{
			"error":       err.Error(),
			"customer_id": customerID,
		})
	}

	return response.Success(c, map[string]interface{}{
		"message": "Logout successful",
	}, "Logout successful")
}
