package handlers

import (
	"Yimaru-Backend/internal/domain"
	"Yimaru-Backend/internal/services/authentication"
	"Yimaru-Backend/internal/web_server/response"
	"fmt"
	"strconv"
	"time"

	"github.com/gofiber/fiber/v2"
	"go.uber.org/zap"
)

type CreateTransactionApproverReq struct {
	FirstName   string `json:"first_name" example:"John"`
	LastName    string `json:"last_name" example:"Doe"`
	Email       string `json:"email" example:"john.doe@example.com"`
	PhoneNumber string `json:"phone_number" example:"1234567890"`
	Password    string `json:"password" example:"password123"`
	CompanyID   int64  `json:"company_id" example:"1"`
}

// CreateTransactionApprover godoc
// @Summary Create transaction approver
// @Description Create transaction approver
// @Tags admin
// @Accept json
// @Produce json
// @Param manger body CreateTransactionApproverReq true "Create transaction approver"
// @Success 200 {object} response.APIResponse
// @Failure 400 {object} response.APIResponse
// @Failure 401 {object} response.APIResponse
// @Failure 500 {object} response.APIResponse
// @Router /api/v1/admin [post]
// func (h *Handler) CreateTransactionApprover(c *fiber.Ctx) error {
// 	var companyID domain.ValidInt64
// 	var req CreateTransactionApproverReq

// 	if err := c.BodyParser(&req); err != nil {
// 		h.mongoLoggerSvc.Info("failed to parse CreateAdmin request",
// 			zap.Int64("status_code", fiber.StatusBadRequest),
// 			zap.Error(err),
// 			zap.Time("timestamp", time.Now()),
// 		)
// 		return fiber.NewError(fiber.StatusBadRequest, "Invalid request:"+err.Error())
// 	}

// 	valErrs, ok := h.validator.Validate(c, req)
// 	if !ok {
// 		var errMsg string
// 		for field, msg := range valErrs {
// 			errMsg += fmt.Sprintf("%s: %s; ", field, msg)
// 		}
// 		h.mongoLoggerSvc.Error("validation failed for CreateAdmin request",
// 			zap.Int64("status_code", fiber.StatusBadRequest),
// 			zap.Any("validation_errors", valErrs),
// 			zap.Time("timestamp", time.Now()),
// 		)
// 		return fiber.NewError(fiber.StatusBadRequest, errMsg)
// 	}

// 	// _, err := h.companySvc.GetCompanyByID(c.Context(), req.CompanyID)
// 	// if err != nil {
// 	// 	h.mongoLoggerSvc.Error("invalid company ID for CreateAdmin",
// 	// 		zap.Int64("status_code", fiber.StatusInternalServerError),
// 	// 		zap.Int64("company_id", req.CompanyID),
// 	// 		zap.Error(err),
// 	// 		zap.Time("timestamp", time.Now()),
// 	// 	)
// 	// 	return fiber.NewError(fiber.StatusInternalServerError, "Company ID is invalid:"+err.Error())
// 	// }
// 	companyID = domain.ValidInt64{
// 		Value: req.CompanyID,
// 		Valid: true,
// 	}

// 	user := domain.CreateUserReq{
// 		FirstName:      req.FirstName,
// 		LastName:       req.LastName,
// 		Email:          req.Email,
// 		PhoneNumber:    req.PhoneNumber,
// 		Password:       req.Password,
// 		Role:           string(domain.RoleTransactionApprover),
// 		OrganizationID: companyID,
// 	}

// 	newUser, err := h.userSvc.CreateUser(c.Context(), user, true)
// 	if err != nil {
// 		h.mongoLoggerSvc.Error("failed to create admin user",
// 			zap.Int64("status_code", fiber.StatusInternalServerError),
// 			zap.Any("request", req),
// 			zap.Error(err),
// 			zap.Time("timestamp", time.Now()),
// 		)
// 		return fiber.NewError(fiber.StatusInternalServerError, "Failed to create admin:"+err.Error())
// 	}

// 	h.mongoLoggerSvc.Info("transaction_approver created successfully",
// 		zap.Int64("transaction_approver_id", newUser.ID),
// 		zap.String("email", newUser.Email),
// 		zap.Time("timestamp", time.Now()),
// 	)

// 	return response.WriteJSON(c, fiber.StatusOK, "Transaction Approver created successfully", nil, nil)
// }

type TransactionApproverRes struct {
	ID            int64       `json:"id"`
	FirstName     string      `json:"first_name"`
	LastName      string      `json:"last_name"`
	Email         string      `json:"email"`
	PhoneNumber   string      `json:"phone_number"`
	Role          domain.Role `json:"role"`
	EmailVerified bool        `json:"email_verified"`
	PhoneVerified bool        `json:"phone_verified"`
	CreatedAt     time.Time   `json:"created_at"`
	UpdatedAt     time.Time   `json:"updated_at"`
	LastLogin     time.Time   `json:"last_login"`
	SuspendedAt   time.Time   `json:"suspended_at"`
	Suspended     bool        `json:"suspended"`
}

// GetAllAdmins godoc
// @Summary Get all Admins
// @Description Get all Admins
// @Tags admin
// @Accept json
// @Produce json
// @Param page query int false "Page number"
// @Param page_size query int false "Page size"
// @Success 200 {object} AdminRes
// @Failure 400 {object} response.APIResponse
// @Failure 401 {object} response.APIResponse
// @Failure 500 {object} response.APIResponse
// @Router /api/v1/t-approver [get]
// func (h *Handler) GetAllTransactionApprovers(c *fiber.Ctx) error {
// 	role := c.Locals("role").(domain.Role)
// 	companyID := c.Locals("company_id").(domain.ValidInt64)

// 	searchQuery := c.Query("query")
// 	searchString := domain.ValidString{
// 		Value: searchQuery,
// 		Valid: searchQuery != "",
// 	}

// 	createdBeforeQuery := c.Query("created_before")
// 	var createdBefore domain.ValidTime
// 	if createdBeforeQuery != "" {
// 		createdBeforeParsed, err := time.Parse(time.RFC3339, createdBeforeQuery)
// 		if err != nil {
// 			h.logger.Info("invalid start_time format", "error", err)
// 			return fiber.NewError(fiber.StatusBadRequest, "Invalid start_time format")
// 		}
// 		createdBefore = domain.ValidTime{
// 			Value: createdBeforeParsed,
// 			Valid: true,
// 		}
// 	}

// 	createdAfterQuery := c.Query("created_after")
// 	var createdAfter domain.ValidTime
// 	if createdAfterQuery != "" {
// 		createdAfterParsed, err := time.Parse(time.RFC3339, createdAfterQuery)
// 		if err != nil {
// 			h.logger.Info("invalid start_time format", "error", err)
// 			return fiber.NewError(fiber.StatusBadRequest, "Invalid start_time format")
// 		}
// 		createdAfter = domain.ValidTime{
// 			Value: createdAfterParsed,
// 			Valid: true,
// 		}
// 	}

// 	var companyIDFilter domain.ValidInt64
// 	if role == domain.RoleSuperAdmin {
// 		companyIDQuery := int64(c.QueryInt("company_id"))
// 		companyIDFilter = domain.ValidInt64{
// 			Value: companyIDQuery,
// 			Valid: companyIDQuery != 0,
// 		}
// 	} else {
// 		if !companyID.Valid {
// 			h.logger.Info("invalid companyID")
// 			return fiber.NewError(fiber.StatusBadRequest, "Unable to get company ID")
// 		}

// 		companyIDFilter = companyID
// 	}

// 	filter := domain.UserFilter{
// 		Role:           string(domain.RoleTransactionApprover),
// 		OrganizationID: companyIDFilter,
// 		Page: domain.ValidInt{
// 			Value: c.QueryInt("page", 1) - 1,
// 			Valid: true,
// 		},
// 		PageSize: domain.ValidInt{
// 			Value: c.QueryInt("page_size", 10),
// 			Valid: true,
// 		},
// 		Query:         searchString,
// 		CreatedBefore: createdBefore,
// 		CreatedAfter:  createdAfter,
// 	}

// 	valErrs, ok := h.validator.Validate(c, filter)
// 	if !ok {
// 		var errMsg string
// 		for field, msg := range valErrs {
// 			errMsg += fmt.Sprintf("%s: %s; ", field, msg)
// 		}
// 		h.mongoLoggerSvc.Info("invalid filter values in GetAllAdmins request",
// 			zap.Int("status_code", fiber.StatusBadRequest),
// 			zap.Any("validation_errors", valErrs),
// 			zap.Time("timestamp", time.Now()),
// 		)
// 		return fiber.NewError(fiber.StatusBadRequest, errMsg)
// 	}

// 	users, total, err := h.userSvc.GetAllUsers(c.Context(), filter)
// 	if err != nil {
// 		h.mongoLoggerSvc.Error("failed to get users from user service",
// 			zap.Int("status_code", fiber.StatusInternalServerError),
// 			zap.Any("filter", filter),
// 			zap.Error(err),
// 			zap.Time("timestamp", time.Now()),
// 		)
// 		return fiber.NewError(fiber.StatusInternalServerError, "Failed to get users"+err.Error())
// 	}

// 	result := make([]TransactionApproverRes, len(users))
// 	for index, admin := range users {
// 		lastLogin, err := h.authSvc.GetLastLogin(c.Context(), admin.ID)
// 		if err != nil {
// 			if err == authentication.ErrRefreshTokenNotFound {
// 				lastLogin = &admin.CreatedAt
// 			} else {
// 				h.mongoLoggerSvc.Error("failed to get last login for admin",
// 					zap.Int("status_code", fiber.StatusInternalServerError),
// 					zap.Int64("admin_id", admin.ID),
// 					zap.Error(err),
// 					zap.Time("timestamp", time.Now()),
// 				)
// 				return fiber.NewError(fiber.StatusInternalServerError, "Failed to retrieve user last login"+err.Error())
// 			}
// 		}

// 		result[index] = TransactionApproverRes{
// 			ID:            admin.ID,
// 			FirstName:     admin.FirstName,
// 			LastName:      admin.LastName,
// 			Email:         admin.Email,
// 			PhoneNumber:   admin.PhoneNumber,
// 			Role:          admin.Role,
// 			EmailVerified: admin.EmailVerified,
// 			PhoneVerified: admin.PhoneVerified,
// 			CreatedAt:     admin.CreatedAt,
// 			UpdatedAt:     admin.UpdatedAt,
// 			SuspendedAt:   admin.SuspendedAt,
// 			Suspended:     admin.Suspended,
// 			LastLogin:     *lastLogin,
// 		}
// 	}

// 	h.mongoLoggerSvc.Info("approvers retrieved successfully",
// 		zap.Int("status_code", fiber.StatusOK),
// 		zap.Int("count", len(result)),
// 		zap.Int("page", filter.Page.Value+1),
// 		zap.Time("timestamp", time.Now()),
// 	)

// 	return response.WritePaginatedJSON(c, fiber.StatusOK, "Admins retrieved successfully", result, nil, filter.Page.Value, int(total))
// }

// GetAdminByID godoc
// @Summary Get admin by id
// @Description Get a single admin by id
// @Tags admin
// @Accept json
// @Produce json
// @Param id path int true "User ID"
// @Success 200 {object} AdminRes
// @Failure 400 {object} response.APIResponse
// @Failure 401 {object} response.APIResponse
// @Failure 500 {object} response.APIResponse
// @Router /api/v1/t-approver/{id} [get]
func (h *Handler) GetTransactionApproverByID(c *fiber.Ctx) error {
	userIDstr := c.Params("id")
	userID, err := strconv.ParseInt(userIDstr, 10, 64)
	if err != nil {
		h.mongoLoggerSvc.Error("invalid admin ID param",
			zap.Int("status_code", fiber.StatusBadRequest),
			zap.String("param", userIDstr),
			zap.Error(err),
			zap.Time("timestamp", time.Now()),
		)
		return fiber.NewError(fiber.StatusBadRequest, "Invalid admin ID")
	}

	user, err := h.userSvc.GetUserByID(c.Context(), userID)
	if err != nil {
		h.mongoLoggerSvc.Error("failed to fetch admin by ID",
			zap.Int("status_code", fiber.StatusInternalServerError),
			zap.Int64("admin_id", userID),
			zap.Error(err),
			zap.Time("timestamp", time.Now()),
		)
		return fiber.NewError(fiber.StatusInternalServerError, "Failed to get admin"+err.Error())
	}

	lastLogin, err := h.authSvc.GetLastLogin(c.Context(), user.ID)
	if err != nil && err != authentication.ErrRefreshTokenNotFound {
		h.mongoLoggerSvc.Error("failed to get admin last login",
			zap.Int("status_code", fiber.StatusInternalServerError),
			zap.Int64("admin_id", user.ID),
			zap.Error(err),
			zap.Time("timestamp", time.Now()),
		)
		return fiber.NewError(fiber.StatusInternalServerError, "Failed to retrieve user last login:"+err.Error())
	}
	if err == authentication.ErrRefreshTokenNotFound {
		lastLogin = &user.CreatedAt
	}

	res := TransactionApproverRes{
		ID:            user.ID,
		FirstName:     user.FirstName,
		LastName:      user.LastName,
		Email:         user.Email,
		PhoneNumber:   user.PhoneNumber,
		Role:          user.Role,
		EmailVerified: user.EmailVerified,
		PhoneVerified: user.PhoneVerified,
		CreatedAt:     user.CreatedAt,
		// SuspendedAt:   user.SuspendedAt,
		// Suspended:     user.Suspended,
		LastLogin: *lastLogin,
	}

	h.mongoLoggerSvc.Info("admin retrieved successfully",
		zap.Int("status_code", fiber.StatusOK),
		zap.Int64("admin_id", user.ID),
		zap.Time("timestamp", time.Now()),
	)

	return response.WriteJSON(c, fiber.StatusOK, "Admin retrieved successfully", res, nil)
}

type updateTransactionApproverReq struct {
	FirstName string `json:"first_name" example:"John"`
	LastName  string `json:"last_name" example:"Doe"`
	Suspended bool   `json:"suspended" example:"false"`
}

// UpdateAdmin godoc
// @Summary Update Admin
// @Description Update Admin
// @Tags admin
// @Accept json
// @Produce json
// @Param admin body updateAdminReq true "Update Admin"
// @Success 200 {object} response.APIResponse
// @Failure 400 {object} response.APIResponse
// @Failure 401 {object} response.APIResponse
// @Failure 500 {object} response.APIResponse
// @Router /api/v1/t-approver/{id} [put]
func (h *Handler) UpdateTransactionApprover(c *fiber.Ctx) error {
	var req updateTransactionApproverReq
	if err := c.BodyParser(&req); err != nil {
		h.mongoLoggerSvc.Error("UpdateTransactionApprover failed - invalid request body",
			zap.Int("status_code", fiber.StatusBadRequest),
			zap.Error(err),
			zap.Time("timestamp", time.Now()),
		)
		return fiber.NewError(fiber.StatusBadRequest, "Invalid request body: "+err.Error())
	}

	if valErrs, ok := h.validator.Validate(c, req); !ok {
		var errMsg string
		for field, msg := range valErrs {
			errMsg += fmt.Sprintf("%s: %s; ", field, msg)
		}
		h.mongoLoggerSvc.Error("UpdateTransactionApprover failed - validation errors",
			zap.Int("status_code", fiber.StatusBadRequest),
			zap.Any("validation_errors", valErrs),
			zap.Time("timestamp", time.Now()),
		)
		return fiber.NewError(fiber.StatusBadRequest, errMsg)
	}

	approverIDStr := c.Params("id")
	approverID, err := strconv.ParseInt(approverIDStr, 10, 64)
	if err != nil {
		h.mongoLoggerSvc.Info("UpdateTransactionApprover failed - invalid approver ID",
			zap.Int("status_code", fiber.StatusBadRequest),
			zap.String("approver_id_param", approverIDStr),
			zap.Error(err),
			zap.Time("timestamp", time.Now()),
		)
		return fiber.NewError(fiber.StatusBadRequest, "Invalid approver ID")
	}

	updateReq := domain.UpdateUserReq{
		UserID:    approverID,
		FirstName: req.FirstName,
		LastName:  req.LastName,
	}

	err = h.userSvc.UpdateUser(c.Context(), updateReq)
	if err != nil {
		h.mongoLoggerSvc.Error("UpdateTransactionApprover failed - user service error",
			zap.Int("status_code", fiber.StatusInternalServerError),
			zap.Int64("approver_id", approverID),
			zap.Error(err),
			zap.Time("timestamp", time.Now()),
		)
		return fiber.NewError(fiber.StatusInternalServerError, "Failed to update approver: "+err.Error())
	}

	h.mongoLoggerSvc.Info("UpdateTransactionApprover succeeded",
		zap.Int("status_code", fiber.StatusOK),
		zap.Int64("approver_id", approverID),
		zap.Time("timestamp", time.Now()),
	)

	return response.WriteJSON(c, fiber.StatusOK, "Transaction approver updated successfully", nil, nil)
}
