package Astrologer

import (
	"errors"
	"fmt"
	"mime/multipart"
	"net/http"
	"sort"
	"strconv"
	"strings"

	dto_astrologer "astrology-api/dto_astrologer"
	"astrology-api/helpers"
	"astrology-api/services_astrologer"

	"github.com/gin-gonic/gin"
	"github.com/gin-gonic/gin/binding"
)

type AstrologerController struct {
	service services_astrologer.AstrologerService
}

func NewAstrologerController(
	service services_astrologer.AstrologerService,
) *AstrologerController {

	return &AstrologerController{
		service: service,
	}
}

func GetUserID(c *gin.Context) uint {

	value, exists := c.Get("user_id")

	if !exists {
		return 0
	}

	userID, ok := value.(uint)

	if !ok {
		return 0
	}

	return userID
}

// Get Complete Profile

func (ac *AstrologerController) GetProfileDetails(c *gin.Context) {

	id := c.Param("id")

	astrologerID, err := strconv.ParseUint(id, 10, 64)
	if err != nil {

		c.JSON(http.StatusBadRequest, gin.H{
			"status":  false,
			"message": "Invalid Astrologer ID",
		})
		return
	}

	data, err := ac.service.GetProfileDetails(uint(astrologerID))
	if err != nil {

		c.JSON(http.StatusBadRequest, gin.H{
			"status":  false,
			"message": err.Error(),
		})
		return
	}

	c.JSON(http.StatusOK, gin.H{
		"status":  true,
		"message": "Profile fetched successfully",
		"data":    data,
	})

}

// Save Basic Profile

func (ac *AstrologerController) SaveBasicProfile(c *gin.Context) {

	var req dto_astrologer.CreateAstrologerProfileRequest

	if err := c.ShouldBindJSON(&req); err != nil {

		c.JSON(http.StatusBadRequest, gin.H{
			"status":  false,
			"message": err.Error(),
		})

		return
	}

	userID := GetUserID(c)

	response, err := ac.service.SaveBasicProfile(userID, req)

	if err != nil {

		c.JSON(http.StatusBadRequest, gin.H{
			"status":  false,
			"message": err.Error(),
		})

		return
	}

	c.JSON(http.StatusOK, gin.H{
		"status":  true,
		"message": "Basic profile saved successfully",
		"data":    response,
	})

}

// Get Profile

func (ac *AstrologerController) GetProfile(c *gin.Context) {

	userID := GetUserID(c)
	profile, err := ac.service.GetProfile(userID)
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{
			"status":  false,
			"message": err.Error(),
		})
		return
	}
	c.JSON(http.StatusOK, gin.H{
		"status":  true,
		"message": "Profile fetched successfully",
		"data":    profile,
	})

}

///////////////////////////////////////////////////////////
// Submit Profile
///////////////////////////////////////////////////////////

func (ac *AstrologerController) SubmitProfile(c *gin.Context) {

	userID := GetUserID(c)
	response, err := ac.service.SubmitProfile(userID)
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{
			"status":  false,
			"message": err.Error(),
		})
		return
	}

	c.JSON(http.StatusOK, gin.H{
		"status":  true,
		"message": "Profile submitted successfully. Waiting for admin approval.",
		"result":  response,
	})
}

///////////////////////////////////////////////////////////
// Upload Profile Image
///////////////////////////////////////////////////////////

// profileImageFields are the form field names accepted for the image, in
// priority order. "profile_image" is the documented one; the rest are what
// clients have actually been sending, and a file arriving under any of them is
// better than a 400 that looks like the file was never attached.
var profileImageFields = []string{
	"profile_image",
	"profile",
	"profile_pic",
	"profile_picture",
	"image",
	"file",
}

// bindProfileImage pulls the uploaded image out of the multipart form.
//
// c.FormFile returning an error used to be reported as "profile image is
// required", which is wrong for the two ways it actually fails: a request that
// is not multipart at all, and a file sent under a different field name. Both
// now say so, and the second lists the field names the request did carry — the
// same treatment bindDocumentUpload gives the document endpoint.
func bindProfileImage(c *gin.Context) (*multipart.FileHeader, error) {

	if !strings.HasPrefix(c.ContentType(), "multipart/form-data") {

		return nil, errors.New(
			"profile image must be sent as multipart/form-data with the file in the \"profile_image\" field — remove any Content-Type header set by hand and let the client set the multipart boundary",
		)
	}

	for _, field := range profileImageFields {

		if file, err := c.FormFile(field); err == nil {
			return file, nil
		}
	}

	// Name what did arrive. A form that carried "profile_image" as a text
	// value, or the file under a field nobody expected, is otherwise
	// indistinguishable from an empty request.
	form, err := c.MultipartForm()

	if err != nil {
		return nil, fmt.Errorf("could not read the uploaded form: %w", err)
	}

	received := []string{}

	for name := range form.File {
		received = append(received, name+" (file)")
	}

	for name := range form.Value {
		received = append(received, name+" (text)")
	}

	sort.Strings(received)

	if len(received) == 0 {
		return nil, errors.New(
			"profile image is required — the request carried no fields at all",
		)
	}

	return nil, fmt.Errorf(
		"no image file found in the \"profile_image\" field; the request carried: %s",
		strings.Join(received, ", "),
	)
}

func (ac *AstrologerController) UploadProfileImage(c *gin.Context) {

	userID := GetUserID(c)
	file, err := bindProfileImage(c)

	if err != nil {

		c.JSON(http.StatusBadRequest, gin.H{
			"status":  false,
			"message": err.Error(),
		})

		return
	}

	resp, err := ac.service.UploadProfileImage(userID, file)

	if err != nil {

		c.JSON(http.StatusBadRequest, gin.H{
			"status":  false,
			"message": err.Error(),
		})

		return
	}

	c.JSON(http.StatusOK, gin.H{
		"status":  true,
		"message": "Profile image uploaded successfully",
		"data":    resp,
	})
}

///////////////////////////////////////////////////////////
// Profile Completion Status
///////////////////////////////////////////////////////////

func (ac *AstrologerController) ProfileStatus(c *gin.Context) {

	userID := GetUserID(c)

	data, err := ac.service.GetProfile(userID)

	if err != nil {

		c.JSON(http.StatusBadRequest, gin.H{
			"status":  false,
			"message": err.Error(),
		})

		return
	}

	c.JSON(http.StatusOK, gin.H{
		"status":  true,
		"message": "Success",
		"data": gin.H{
			"profile_status":        data.ProfileStatus,
			"completion_percentage": data.CompletionPercentage,
			"current_step":          data.CurrentStep,
			"is_profile_completed":  data.IsProfileCompleted,
		},
	})
}

func (ac *AstrologerController) SaveLanguages(c *gin.Context) {

	var req dto_astrologer.SaveLanguagesRequest

	if err := c.ShouldBindJSON(&req); err != nil {

		c.JSON(http.StatusBadRequest, gin.H{
			"status":  false,
			"message": err.Error(),
		})
		return
	}

	userID := GetUserID(c)
	response, err := ac.service.SaveLanguages(userID, req)
	if err != nil {

		c.JSON(http.StatusBadRequest, gin.H{
			"status":  false,
			"message": err.Error(),
		})
		return
	}

	c.JSON(http.StatusOK, gin.H{
		"status":  true,
		"message": "Languages saved successfully",
		"result":  response,
	})

}

func (ac *AstrologerController) SaveSkills(c *gin.Context) {

	var req dto_astrologer.SaveSkillsRequest

	if err := c.ShouldBindJSON(&req); err != nil {

		c.JSON(http.StatusBadRequest, gin.H{
			"status":  false,
			"message": err.Error(),
		})
		return
	}

	userID := GetUserID(c)
	response, err := ac.service.SaveSkills(userID, req)

	if err != nil {

		c.JSON(http.StatusBadRequest, gin.H{
			"status":  false,
			"message": err.Error(),
		})
		return
	}

	c.JSON(http.StatusOK, gin.H{
		"status":  true,
		"message": "Skills saved successfully",
		"result":  response,
	})

}

func (ac *AstrologerController) SaveEducation(c *gin.Context) {

	var req dto_astrologer.EducationRequest

	if err := c.ShouldBindJSON(&req); err != nil {

		c.JSON(http.StatusBadRequest, gin.H{
			"status":  false,
			"message": err.Error(),
		})
		return
	}

	userID := GetUserID(c)

	response, err := ac.service.SaveEducation(userID, req)

	if err != nil {

		c.JSON(http.StatusBadRequest, gin.H{
			"status":  false,
			"message": err.Error(),
		})
		return
	}

	c.JSON(http.StatusOK, gin.H{
		"status":  true,
		"message": "Education details saved successfully",
		"result":  response,
	})
}

func (ac *AstrologerController) SaveProfessional(c *gin.Context) {

	var req dto_astrologer.ProfessionalRequest

	if err := c.ShouldBindJSON(&req); err != nil {

		c.JSON(http.StatusBadRequest, gin.H{
			"status":  false,
			"message": err.Error(),
		})
		return
	}

	userID := GetUserID(c)
	response, err := ac.service.SaveProfessional(userID, req)

	if err != nil {

		c.JSON(http.StatusBadRequest, gin.H{
			"status":  false,
			"message": err.Error(),
		})
		return
	}

	c.JSON(http.StatusOK, gin.H{
		"status":  true,
		"message": "Professional details saved successfully",
		"result":  response,
	})

}

func (ac *AstrologerController) SaveExperience(c *gin.Context) {

	var req dto_astrologer.ExperienceRequest

	if err := c.ShouldBindJSON(&req); err != nil {

		c.JSON(http.StatusBadRequest, gin.H{
			"status":  false,
			"message": err.Error(),
		})
		return
	}

	userID := GetUserID(c)
	response, err := ac.service.SaveExperience(userID, req)

	if err != nil {

		c.JSON(http.StatusBadRequest, gin.H{
			"status":  false,
			"message": err.Error(),
		})
		return
	}

	c.JSON(http.StatusOK, gin.H{
		"status":  true,
		"message": "Experience saved successfully",
		"result":  response,
	})

}

func (ac *AstrologerController) SaveBankAccount(c *gin.Context) {

	var req dto_astrologer.BankRequest

	if err := c.ShouldBindJSON(&req); err != nil {

		c.JSON(http.StatusBadRequest, gin.H{
			"status":  false,
			"message": err.Error(),
		})
		return
	}

	userID := GetUserID(c)
	response, err := ac.service.SaveBankAccount(userID, req)
	if err != nil {

		c.JSON(http.StatusBadRequest, gin.H{
			"status":  false,
			"message": err.Error(),
		})
		return
	}

	c.JSON(http.StatusOK, gin.H{
		"status":  true,
		"message": "Bank details saved successfully",
		"result":  response,
	})

}

// bindDocumentUpload reads the document form off a request.
//
// Both document endpoints always carry a file, so the request is always
// multipart — but ShouldBind picks its binder from Content-Type, and a client
// that leaves an "application/json" header on a form-data request (Postman
// keeps a hand-added header when the body type is switched) sent the multipart
// body through the JSON decoder. That surfaced as
//
//	{"status":false,"message":"invalid character '-' in numeric literal"}
//
// which is the JSON decoder choking on the leading dashes of the multipart
// boundary, and says nothing about the actual mistake. Binding multipart
// explicitly removes the guess, and the Content-Type is checked first so a
// genuinely non-multipart request gets told what to send.
func bindDocumentUpload(c *gin.Context, req *dto_astrologer.UploadDocumentRequest) error {

	if !strings.HasPrefix(c.ContentType(), "multipart/form-data") {

		return errors.New(
			"document upload must be sent as multipart/form-data with the file in the \"document\" field — remove any Content-Type header set by hand and let the client set the multipart boundary",
		)
	}

	return c.ShouldBindWith(req, binding.FormMultipart)
}

func (pc *AstrologerController) UploadDocument(c *gin.Context) {

	userID := GetUserID(c)

	var req dto_astrologer.UploadDocumentRequest

	if err := bindDocumentUpload(c, &req); err != nil {

		c.JSON(http.StatusBadRequest, gin.H{
			"status":  false,
			"message": err.Error(),
		})

		return
	}

	file, err := c.FormFile("document")

	if err != nil {

		c.JSON(http.StatusBadRequest, gin.H{
			"status":  false,
			"message": "Document file is required",
		})

		return
	}

	response, err := pc.service.UploadDocument(userID, req, file)
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{
			"status":  false,
			"message": err.Error(),
		})
		return
	}

	c.JSON(http.StatusOK, gin.H{
		"status":  true,
		"message": "Document uploaded successfully",
		"data":    response,
	})
}

func (ac *AstrologerController) GetProfileProgress(c *gin.Context) {

	userID := GetUserID(c)

	data, err := ac.service.GetProfileProgress(userID)

	if err != nil {

		c.JSON(http.StatusBadRequest, gin.H{
			"status":  false,
			"message": err.Error(),
		})

		return
	}

	c.JSON(http.StatusOK, gin.H{
		"status":  true,
		"message": "Profile progress fetched successfully",
		"data":    data,
	})
}

func (ac *AstrologerController) ChangeStatus(c *gin.Context) {

	var req dto_astrologer.ChangeStatusRequest

	if err := c.ShouldBindJSON(&req); err != nil {

		c.JSON(http.StatusBadRequest, gin.H{
			"status":  false,
			"message": err.Error(),
		})
		return
	}

	userID := GetUserID(c)

	if err := ac.service.ChangeStatus(userID, req); err != nil {

		c.JSON(http.StatusBadRequest, gin.H{
			"status":  false,
			"message": err.Error(),
		})
		return
	}

	c.JSON(http.StatusOK, gin.H{
		"status":  true,
		"message": "Status updated successfully",
	})
}

func (ac *AstrologerController) DeleteAccount(c *gin.Context) {

	userID := GetUserID(c)

	if err := ac.service.DeleteAccount(userID); err != nil {

		c.JSON(http.StatusBadRequest, gin.H{
			"status":  false,
			"message": err.Error(),
		})
		return
	}

	c.JSON(http.StatusOK, gin.H{
		"status":  true,
		"message": "Account deleted successfully",
	})
}

func (ac *AstrologerController) GetMasterLanguages(c *gin.Context) {

	userID := GetUserID(c)

	data, err := ac.service.GetMasterLanguages(userID)

	if err != nil {

		c.JSON(http.StatusBadRequest, gin.H{
			"status":  false,
			"message": err.Error(),
		})

		return
	}

	c.JSON(http.StatusOK, gin.H{
		"status":  true,
		"message": "Languages fetched successfully",
		"data":    data,
	})
}

func (ac *AstrologerController) GetMasterSkills(c *gin.Context) {

	userID := GetUserID(c)

	data, err := ac.service.GetMasterSkills(userID)

	if err != nil {

		c.JSON(http.StatusBadRequest, gin.H{
			"status":  false,
			"message": err.Error(),
		})
		return
	}

	c.JSON(http.StatusOK, gin.H{
		"status":  true,
		"message": "Skills fetched successfully",
		"data":    data,
	})
}

func (pc *AstrologerController) GetMasterDocumentTypes(c *gin.Context) {

	data, err := pc.service.GetMasterDocumentTypes()

	if err != nil {

		c.JSON(http.StatusBadRequest, gin.H{
			"status":  false,
			"message": err.Error(),
		})

		return
	}

	c.JSON(http.StatusOK, gin.H{
		"status":  true,
		"message": "Master document types fetched successfully",
		"data":    data,
	})
}

func (c *AstrologerController) GetDeviceTypes(ctx *gin.Context) {

	data, err := c.service.GetDeviceTypes()

	if err != nil {

		ctx.JSON(http.StatusBadRequest, gin.H{
			"status":  false,
			"message": err.Error(),
		})
		return
	}

	ctx.JSON(http.StatusOK, gin.H{
		"status":  true,
		"message": "Device types Fetched Successfully",
		"data":    data,
	})

}

func (c *AstrologerController) GetWorkingHours(ctx *gin.Context) {

	data, err := c.service.GetWorkingHours()

	if err != nil {

		ctx.JSON(http.StatusBadRequest, gin.H{
			"status":  false,
			"message": err.Error(),
		})

		return
	}

	ctx.JSON(http.StatusOK, gin.H{
		"status":  true,
		"message": "Working hours Fetched Successfully",
		"data":    data,
	})

}

func (c *AstrologerController) SaveAvailability(ctx *gin.Context) {

	userID := ctx.GetUint("user_id")

	var req dto_astrologer.SaveAvailabilityRequest

	if err := ctx.ShouldBindJSON(&req); err != nil {

		ctx.JSON(http.StatusBadRequest, gin.H{
			"status":  false,
			"message": err.Error(),
		})

		return
	}

	response, err := c.service.SaveAvailability(userID, req)

	if err != nil {

		ctx.JSON(http.StatusBadRequest, gin.H{
			"status":  false,
			"message": err.Error(),
		})

		return
	}

	ctx.JSON(http.StatusOK, gin.H{
		"status":  true,
		"message": "Availability Saved Successfully",
		"data":    response,
	})
}

func (ac *AstrologerController) GetAvailability(c *gin.Context) {

	userID := GetUserID(c)
	response, err := ac.service.GetAvailability(userID)

	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{
			"status":  false,
			"message": err.Error(),
		})
		return
	}

	c.JSON(http.StatusOK, gin.H{
		"status":  true,
		"message": "Availability Fetched Successfully",
		"result":  response,
	})

}

func (c *AstrologerController) UpdateProfile(ctx *gin.Context) {

	userID := ctx.MustGet("user_id").(uint)
	var req dto_astrologer.UpdateProfileRequest

	if err := ctx.ShouldBindJSON(&req); err != nil {

		ctx.JSON(
			http.StatusBadRequest,
			helpers.ErrorResponse(err.Error()),
		)
		return

	}

	response, err := c.service.UpdateProfile(userID, req)
	if err != nil {

		ctx.JSON(
			http.StatusBadRequest,
			helpers.ErrorResponse(err.Error()),
		)

		return
	}

	ctx.JSON(
		http.StatusOK,
		helpers.SuccessResponse("Profile updated Successfully.", response),
	)
}

func (c *AstrologerController) UpdateProfileImage(ctx *gin.Context) {

	userID := ctx.MustGet("user_id").(uint)

	file, err := bindProfileImage(ctx)

	if err != nil {

		ctx.JSON(
			http.StatusBadRequest,
			helpers.ErrorResponse(err.Error()),
		)

		return
	}

	// UpdateProfileImage, not UploadProfileImage: this route is the maintenance
	// endpoint, so it must go through the update guard rather than the step-4
	// creation guard. Wired to the step method, it refused an approved
	// astrologer's image change with "profile has already been submitted".
	response, err := c.service.UpdateProfileImage(userID, file)

	if err != nil {

		ctx.JSON(
			http.StatusBadRequest,
			helpers.ErrorResponse(err.Error()),
		)

		return
	}

	ctx.JSON(
		http.StatusOK,
		helpers.SuccessResponse(
			"Profile image updated Successfully.",
			response,
		),
	)
}

func (c *AstrologerController) DeleteProfileImage(ctx *gin.Context) {

	userID := ctx.MustGet("user_id").(uint)

	response, err := c.service.DeleteProfileImage(userID)

	if err != nil {

		ctx.JSON(
			http.StatusBadRequest,
			helpers.ErrorResponse(err.Error()),
		)

		return
	}

	ctx.JSON(
		http.StatusOK,
		helpers.SuccessResponse(
			"Profile image Deleted Successfully.",
			response,
		),
	)
}

func (c *AstrologerController) UpdateAvailability(ctx *gin.Context) {

	userID := ctx.MustGet("user_id").(uint)

	var req dto_astrologer.SaveAvailabilityRequest

	if err := ctx.ShouldBindJSON(&req); err != nil {
		ctx.JSON(http.StatusBadRequest,
			helpers.ErrorResponse(err.Error()))
		return
	}

	resp, err := c.service.UpdateAvailability(userID, req)

	if err != nil {
		ctx.JSON(http.StatusBadRequest,
			helpers.ErrorResponse(err.Error()))
		return
	}

	ctx.JSON(http.StatusOK,
		helpers.SuccessResponse(
			"Availability updated Successfully.",
			resp,
		),
	)
}

func (c *AstrologerController) UpdateBankAccount(ctx *gin.Context) {

	userID := ctx.MustGet("user_id").(uint)

	var req dto_astrologer.UpdateBankAccountRequest

	if err := ctx.ShouldBindJSON(&req); err != nil {
		ctx.JSON(
			http.StatusBadRequest,
			helpers.ErrorResponse(err.Error()),
		)
		return
	}

	resp, err := c.service.UpdateBankAccount(userID, req)

	if err != nil {
		ctx.JSON(
			http.StatusBadRequest,
			helpers.ErrorResponse(err.Error()),
		)
		return
	}

	ctx.JSON(
		http.StatusOK,
		helpers.SuccessResponse(
			"Bank account updated successfully.",
			resp,
		),
	)
}

func (c *AstrologerController) UpdateSkills(ctx *gin.Context) {

	userID := ctx.MustGet("user_id").(uint)

	var req dto_astrologer.UpdateSkillsRequest

	if err := ctx.ShouldBindJSON(&req); err != nil {
		ctx.JSON(
			http.StatusBadRequest,
			helpers.ErrorResponse(err.Error()),
		)
		return
	}

	resp, err := c.service.UpdateSkills(userID, req)

	if err != nil {
		ctx.JSON(
			http.StatusBadRequest,
			helpers.ErrorResponse(err.Error()),
		)
		return
	}

	ctx.JSON(
		http.StatusOK,
		helpers.SuccessResponse(
			"Skills updated successfully.",
			resp,
		),
	)
}

func (c *AstrologerController) UpdateLanguages(ctx *gin.Context) {

	userID := ctx.MustGet("user_id").(uint)

	var req dto_astrologer.UpdateLanguagesRequest

	if err := ctx.ShouldBindJSON(&req); err != nil {

		ctx.JSON(
			http.StatusBadRequest,
			helpers.ErrorResponse(err.Error()),
		)

		return
	}

	response, err := c.service.UpdateLanguages(
		userID,
		req,
	)

	if err != nil {

		ctx.JSON(
			http.StatusBadRequest,
			helpers.ErrorResponse(err.Error()),
		)

		return
	}

	ctx.JSON(
		http.StatusOK,
		helpers.SuccessResponse(
			"Languages updated successfully.",
			response,
		),
	)
}

func (c *AstrologerController) UpdateEducation(ctx *gin.Context) {

	userID := ctx.MustGet("user_id").(uint)

	var req dto_astrologer.UpdateEducationRequest

	if err := ctx.ShouldBindJSON(&req); err != nil {
		ctx.JSON(http.StatusBadRequest,
			helpers.ErrorResponse(err.Error()))
		return
	}

	resp, err := c.service.UpdateEducation(userID, req)
	if err != nil {
		ctx.JSON(http.StatusBadRequest,
			helpers.ErrorResponse(err.Error()))
		return
	}

	ctx.JSON(http.StatusOK,
		helpers.SuccessResponse(
			"Education updated successfully.",
			resp,
		),
	)
}

func (c *AstrologerController) UpdateProfessional(ctx *gin.Context) {
	userID := ctx.MustGet("user_id").(uint)
	var req dto_astrologer.UpdateProfessionalRequest
	if err := ctx.ShouldBindJSON(&req); err != nil {
		ctx.JSON(
			http.StatusBadRequest,
			helpers.ErrorResponse(err.Error()),
		)
		return
	}
	resp, err := c.service.UpdateProfessional(
		userID,
		req,
	)

	if err != nil {
		ctx.JSON(
			http.StatusBadRequest,
			helpers.ErrorResponse(err.Error()),
		)
		return
	}
	ctx.JSON(
		http.StatusOK,
		helpers.SuccessResponse(
			"Professional details updated successfully.",
			resp,
		),
	)
}

func (c *AstrologerController) UpdateExperience(ctx *gin.Context) {
	userID := ctx.MustGet("user_id").(uint)
	var req dto_astrologer.UpdateExperienceRequest
	if err := ctx.ShouldBindJSON(&req); err != nil {
		ctx.JSON(
			http.StatusBadRequest,
			helpers.ErrorResponse(err.Error()),
		)
		return
	}
	resp, err := c.service.UpdateExperience(
		userID,
		req,
	)
	if err != nil {
		ctx.JSON(
			http.StatusBadRequest,
			helpers.ErrorResponse(err.Error()),
		)
		return
	}
	ctx.JSON(
		http.StatusOK,
		helpers.SuccessResponse(
			"Experience details updated successfully.",
			resp,
		),
	)
}

func (c *AstrologerController) UpdateDocument(ctx *gin.Context) {

	userID := ctx.MustGet("user_id").(uint)
	var req dto_astrologer.UploadDocumentRequest
	if err := bindDocumentUpload(ctx, &req); err != nil {
		ctx.JSON(
			http.StatusBadRequest,
			helpers.ErrorResponse(err.Error()),
		)
		return
	}
	file, _ := ctx.FormFile("document")
	response, err := c.service.UpdateDocument(
		userID,
		req,
		file,
	)
	if err != nil {
		ctx.JSON(
			http.StatusBadRequest,
			helpers.ErrorResponse(err.Error()),
		)
		return
	}
	ctx.JSON(
		http.StatusOK,
		helpers.SuccessResponse("Document updated successfully.", response),
	)
}
