// RMDC Module Standard Structure Example
// This file demonstrates the recommended project structure for RMDC business modules

package main

/*
Directory Structure:

rmdc-{module-name}/
├── cmd/
│   └── main.go                 # Entry point
├── configs/
│   └── config.yaml             # Configuration file
├── internal/
│   ├── config/
│   │   └── config.go           # Config struct and loader
│   ├── dao/
│   │   └── {entity}_dao.go     # Data access layer
│   ├── handler/
│   │   └── {feature}_handler.go # HTTP handlers
│   ├── model/
│   │   ├── dto/
│   │   │   ├── request.go      # Request DTOs
│   │   │   └── response.go     # Response DTOs
│   │   └── entity/
│   │       └── {table}.go      # Database entities
│   └── service/
│       └── {feature}_service.go # Business logic
├── pkg/
│   └── {shared}/               # Shared packages
├── go.mod
└── go.sum
*/

import (
	"context"
	"net/http"

	"github.com/gin-gonic/gin"
	"gorm.io/gorm"
)

// ============== Entity Layer ==============

// Project represents the database entity
type Project struct {
	ID        int64  `gorm:"primaryKey" json:"id"`
	ProjectID string `gorm:"uniqueIndex;size:64" json:"project_id"`
	Name      string `gorm:"size:128" json:"name"`
	Namespace string `gorm:"uniqueIndex;size:64" json:"namespace"`
	Status    string `gorm:"size:32" json:"status"`
}

func (Project) TableName() string {
	return "projects"
}

// ============== DTO Layer ==============

// CreateProjectRequest is the request DTO
type CreateProjectRequest struct {
	Name      string `json:"name" binding:"required"`
	Namespace string `json:"namespace" binding:"required"`
}

// ProjectResponse is the response DTO
type ProjectResponse struct {
	Code    int         `json:"code"`
	Message string      `json:"message"`
	Data    interface{} `json:"data"`
}

// ============== DAO Layer ==============

// ProjectDAO handles database operations
type ProjectDAO struct {
	db *gorm.DB
}

func NewProjectDAO(db *gorm.DB) *ProjectDAO {
	return &ProjectDAO{db: db}
}

func (d *ProjectDAO) Create(ctx context.Context, project *Project) error {
	return d.db.WithContext(ctx).Create(project).Error
}

func (d *ProjectDAO) GetByID(ctx context.Context, id int64) (*Project, error) {
	var project Project
	err := d.db.WithContext(ctx).First(&project, id).Error
	return &project, err
}

// ============== Service Layer ==============

// ProjectService contains business logic
type ProjectService struct {
	dao *ProjectDAO
}

func NewProjectService(dao *ProjectDAO) *ProjectService {
	return &ProjectService{dao: dao}
}

func (s *ProjectService) CreateProject(ctx context.Context, req *CreateProjectRequest) (*Project, error) {
	project := &Project{
		Name:      req.Name,
		Namespace: req.Namespace,
		Status:    "PENDING",
	}
	// Business logic: generate project_id
	project.ProjectID = "proj_" + req.Namespace

	if err := s.dao.Create(ctx, project); err != nil {
		return nil, err
	}
	return project, nil
}

// ============== Handler Layer ==============

// ProjectHandler handles HTTP requests
type ProjectHandler struct {
	service *ProjectService
}

func NewProjectHandler(service *ProjectService) *ProjectHandler {
	return &ProjectHandler{service: service}
}

// CreateProject godoc
// @Summary Create a new project
// @Tags projects
// @Accept json
// @Produce json
// @Param request body CreateProjectRequest true "Create project request"
// @Success 200 {object} ProjectResponse
// @Router /api/projects/create [post]
func (h *ProjectHandler) CreateProject(c *gin.Context) {
	var req CreateProjectRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(http.StatusBadRequest, ProjectResponse{
			Code:    10004,
			Message: "Invalid parameters: " + err.Error(),
		})
		return
	}

	project, err := h.service.CreateProject(c.Request.Context(), &req)
	if err != nil {
		c.JSON(http.StatusInternalServerError, ProjectResponse{
			Code:    10005,
			Message: "Failed to create project: " + err.Error(),
		})
		return
	}

	c.JSON(http.StatusOK, ProjectResponse{
		Code:    0,
		Message: "success",
		Data:    project,
	})
}

// ============== Router Registration ==============

// RegisterRoutes registers module routes to the router group
func RegisterRoutes(r *gin.RouterGroup, handler *ProjectHandler) {
	projects := r.Group("/projects")
	{
		projects.POST("/create", handler.CreateProject)
		// projects.POST("/list", handler.ListProjects)
		// projects.POST("/detail", handler.GetProject)
		// projects.POST("/update", handler.UpdateProject)
		// projects.POST("/delete", handler.DeleteProject)
	}
}
