package httpapi

import (
	"net/http"

	"github.com/gin-gonic/gin"

	"productier/apps/backend/internal/store"
)

func (s *Server) registerCRMRoutes(group *gin.RouterGroup) {
	// Contacts
	group.GET("/contacts", func(c *gin.Context) {
		workspaceSlug := c.Query("workspaceSlug")
		if _, ok := s.requireWorkspaceMember(c, workspaceSlug); !ok {
			return
		}
		c.JSON(http.StatusOK, gin.H{"data": s.store.ListContacts(workspaceSlug)})
	})

	group.GET("/contacts/:contactId", func(c *gin.Context) {
		contact, err := s.store.GetContactByID(c.Param("contactId"))
		if err != nil {
			s.writeStatusError(c, http.StatusNotFound, err.Error())
			return
		}
		if _, ok := s.requireWorkspaceMember(c, contact.WorkspaceSlug); !ok {
			return
		}
		c.JSON(http.StatusOK, gin.H{"data": contact})
	})

	group.POST("/contacts", func(c *gin.Context) {
		var input store.CreateContactInput
		if err := c.ShouldBindJSON(&input); err != nil {
			s.writeStatusError(c, http.StatusBadRequest, err.Error())
			return
		}
		if _, ok := s.requireWorkspaceMember(c, input.WorkspaceSlug); !ok {
			return
		}
		contact := s.store.CreateContact(input)
		c.JSON(http.StatusCreated, gin.H{"data": contact})
	})

	group.PATCH("/contacts/:contactId", func(c *gin.Context) {
		contact, err := s.store.GetContactByID(c.Param("contactId"))
		if err != nil {
			s.writeStatusError(c, http.StatusNotFound, err.Error())
			return
		}
		if _, ok := s.requireWorkspaceMember(c, contact.WorkspaceSlug); !ok {
			return
		}

		var input store.UpdateContactInput
		if err := c.ShouldBindJSON(&input); err != nil {
			s.writeStatusError(c, http.StatusBadRequest, err.Error())
			return
		}

		updated, err := s.store.UpdateContact(c.Param("contactId"), input)
		if err != nil {
			s.writeStatusError(c, http.StatusInternalServerError, err.Error())
			return
		}
		c.JSON(http.StatusOK, gin.H{"data": updated})
	})

	group.DELETE("/contacts/:contactId", func(c *gin.Context) {
		contact, err := s.store.GetContactByID(c.Param("contactId"))
		if err != nil {
			s.writeStatusError(c, http.StatusNotFound, err.Error())
			return
		}
		if _, ok := s.requireWorkspaceMember(c, contact.WorkspaceSlug); !ok {
			return
		}

		if err := s.store.DeleteContact(c.Param("contactId")); err != nil {
			s.writeStatusError(c, http.StatusInternalServerError, err.Error())
			return
		}
		c.JSON(http.StatusOK, gin.H{"ok": true})
	})

	// Companies
	group.GET("/companies", func(c *gin.Context) {
		workspaceSlug := c.Query("workspaceSlug")
		if _, ok := s.requireWorkspaceMember(c, workspaceSlug); !ok {
			return
		}
		c.JSON(http.StatusOK, gin.H{"data": s.store.ListCompanies(workspaceSlug)})
	})

	group.GET("/companies/:companyId", func(c *gin.Context) {
		company, err := s.store.GetCompanyByID(c.Param("companyId"))
		if err != nil {
			s.writeStatusError(c, http.StatusNotFound, err.Error())
			return
		}
		if _, ok := s.requireWorkspaceMember(c, company.WorkspaceSlug); !ok {
			return
		}
		c.JSON(http.StatusOK, gin.H{"data": company})
	})

	group.POST("/companies", func(c *gin.Context) {
		var input store.CreateCompanyInput
		if err := c.ShouldBindJSON(&input); err != nil {
			s.writeStatusError(c, http.StatusBadRequest, err.Error())
			return
		}
		if _, ok := s.requireWorkspaceMember(c, input.WorkspaceSlug); !ok {
			return
		}
		company := s.store.CreateCompany(input)
		c.JSON(http.StatusCreated, gin.H{"data": company})
	})

	group.PATCH("/companies/:companyId", func(c *gin.Context) {
		company, err := s.store.GetCompanyByID(c.Param("companyId"))
		if err != nil {
			s.writeStatusError(c, http.StatusNotFound, err.Error())
			return
		}
		if _, ok := s.requireWorkspaceMember(c, company.WorkspaceSlug); !ok {
			return
		}

		var input store.UpdateCompanyInput
		if err := c.ShouldBindJSON(&input); err != nil {
			s.writeStatusError(c, http.StatusBadRequest, err.Error())
			return
		}

		updated, err := s.store.UpdateCompany(c.Param("companyId"), input)
		if err != nil {
			s.writeStatusError(c, http.StatusInternalServerError, err.Error())
			return
		}
		c.JSON(http.StatusOK, gin.H{"data": updated})
	})

	group.DELETE("/companies/:companyId", func(c *gin.Context) {
		company, err := s.store.GetCompanyByID(c.Param("companyId"))
		if err != nil {
			s.writeStatusError(c, http.StatusNotFound, err.Error())
			return
		}
		if _, ok := s.requireWorkspaceMember(c, company.WorkspaceSlug); !ok {
			return
		}

		if err := s.store.DeleteCompany(c.Param("companyId")); err != nil {
			s.writeStatusError(c, http.StatusInternalServerError, err.Error())
			return
		}
		c.JSON(http.StatusOK, gin.H{"ok": true})
	})

	// Contact-Task linking
	group.POST("/contacts/:contactId/tasks/:taskId", func(c *gin.Context) {
		contact, err := s.store.GetContactByID(c.Param("contactId"))
		if err != nil {
			s.writeStatusError(c, http.StatusNotFound, err.Error())
			return
		}
		if _, ok := s.requireWorkspaceMember(c, contact.WorkspaceSlug); !ok {
			return
		}

		if err := s.store.LinkContactToTask(c.Param("contactId"), c.Param("taskId")); err != nil {
			s.writeStatusError(c, http.StatusInternalServerError, err.Error())
			return
		}
		c.JSON(http.StatusOK, gin.H{"ok": true})
	})

	group.DELETE("/contacts/:contactId/tasks/:taskId", func(c *gin.Context) {
		contact, err := s.store.GetContactByID(c.Param("contactId"))
		if err != nil {
			s.writeStatusError(c, http.StatusNotFound, err.Error())
			return
		}
		if _, ok := s.requireWorkspaceMember(c, contact.WorkspaceSlug); !ok {
			return
		}

		if err := s.store.UnlinkContactFromTask(c.Param("contactId"), c.Param("taskId")); err != nil {
			s.writeStatusError(c, http.StatusInternalServerError, err.Error())
			return
		}
		c.JSON(http.StatusOK, gin.H{"ok": true})
	})

	// Contact-Event linking
	group.POST("/contacts/:contactId/events/:eventId", func(c *gin.Context) {
		contact, err := s.store.GetContactByID(c.Param("contactId"))
		if err != nil {
			s.writeStatusError(c, http.StatusNotFound, err.Error())
			return
		}
		if _, ok := s.requireWorkspaceMember(c, contact.WorkspaceSlug); !ok {
			return
		}

		if err := s.store.LinkContactToEvent(c.Param("contactId"), c.Param("eventId")); err != nil {
			s.writeStatusError(c, http.StatusInternalServerError, err.Error())
			return
		}
		c.JSON(http.StatusOK, gin.H{"ok": true})
	})
}