package handlers

import (
	"net/http"
	"time"

	"github.com/breakpilot/consent-service/internal/services/jitsi"
	"github.com/breakpilot/consent-service/internal/services/matrix"
	"github.com/gin-gonic/gin"
)

// CommunicationHandlers handles Matrix and Jitsi API endpoints
type CommunicationHandlers struct {
	matrixService *matrix.MatrixService
	jitsiService  *jitsi.JitsiService
}

// NewCommunicationHandlers creates new communication handlers
func NewCommunicationHandlers(matrixSvc *matrix.MatrixService, jitsiSvc *jitsi.JitsiService) *CommunicationHandlers {
	return &CommunicationHandlers{
		matrixService: matrixSvc,
		jitsiService:  jitsiSvc,
	}
}

// ========================================
// Health & Status Endpoints
// ========================================

// GetCommunicationStatus returns status of Matrix and Jitsi services
func (h *CommunicationHandlers) GetCommunicationStatus(c *gin.Context) {
	ctx := c.Request.Context()

	status := gin.H{
		"timestamp": time.Now().UTC().Format(time.RFC3339),
	}

	// Check Matrix
	if h.matrixService != nil {
		matrixErr := h.matrixService.HealthCheck(ctx)
		status["matrix"] = gin.H{
			"enabled":     true,
			"healthy":     matrixErr == nil,
			"server_name": h.matrixService.GetServerName(),
			"error":       errToString(matrixErr),
		}
	} else {
		status["matrix"] = gin.H{
			"enabled": false,
			"healthy": false,
		}
	}

	// Check Jitsi
	if h.jitsiService != nil {
		jitsiErr := h.jitsiService.HealthCheck(ctx)
		serverInfo := h.jitsiService.GetServerInfo()
		status["jitsi"] = gin.H{
			"enabled":      true,
			"healthy":      jitsiErr == nil,
			"base_url":     serverInfo["base_url"],
			"auth_enabled": serverInfo["auth_enabled"],
			"error":        errToString(jitsiErr),
		}
	} else {
		status["jitsi"] = gin.H{
			"enabled": false,
			"healthy": false,
		}
	}

	c.JSON(http.StatusOK, status)
}

// ========================================
// Matrix Room Endpoints
// ========================================

// CreateRoomRequest for creating Matrix rooms
type CreateRoomRequest struct {
	Type         string   `json:"type" binding:"required"` // "class_info", "student_dm", "parent_rep"
	ClassName    string   `json:"class_name"`
	SchoolName   string   `json:"school_name"`
	StudentName  string   `json:"student_name,omitempty"`
	TeacherIDs   []string `json:"teacher_ids"`
	ParentIDs    []string `json:"parent_ids,omitempty"`
	ParentRepIDs []string `json:"parent_rep_ids,omitempty"`
}

// CreateRoom creates a new Matrix room based on type
func (h *CommunicationHandlers) CreateRoom(c *gin.Context) {
	if h.matrixService == nil {
		c.JSON(http.StatusServiceUnavailable, gin.H{"error": "Matrix service not configured"})
		return
	}

	var req CreateRoomRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}

	ctx := c.Request.Context()
	var resp *matrix.CreateRoomResponse
	var err error

	switch req.Type {
	case "class_info":
		resp, err = h.matrixService.CreateClassInfoRoom(ctx, req.ClassName, req.SchoolName, req.TeacherIDs)
	case "student_dm":
		resp, err = h.matrixService.CreateStudentDMRoom(ctx, req.StudentName, req.ClassName, req.TeacherIDs, req.ParentIDs)
	case "parent_rep":
		resp, err = h.matrixService.CreateParentRepRoom(ctx, req.ClassName, req.TeacherIDs, req.ParentRepIDs)
	default:
		c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid room type. Use: class_info, student_dm, parent_rep"})
		return
	}

	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}

	c.JSON(http.StatusCreated, gin.H{
		"room_id": resp.RoomID,
		"type":    req.Type,
	})
}

// InviteUserRequest for inviting users to rooms
type InviteUserRequest struct {
	RoomID string `json:"room_id" binding:"required"`
	UserID string `json:"user_id" binding:"required"`
}

// InviteUser invites a user to a Matrix room
func (h *CommunicationHandlers) InviteUser(c *gin.Context) {
	if h.matrixService == nil {
		c.JSON(http.StatusServiceUnavailable, gin.H{"error": "Matrix service not configured"})
		return
	}

	var req InviteUserRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}

	ctx := c.Request.Context()
	if err := h.matrixService.InviteUser(ctx, req.RoomID, req.UserID); err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}

	c.JSON(http.StatusOK, gin.H{"success": true})
}

// SendMessageRequest for sending messages
type SendMessageRequest struct {
	RoomID  string `json:"room_id" binding:"required"`
	Message string `json:"message" binding:"required"`
	HTML    string `json:"html,omitempty"`
}

// SendMessage sends a message to a Matrix room
func (h *CommunicationHandlers) SendMessage(c *gin.Context) {
	if h.matrixService == nil {
		c.JSON(http.StatusServiceUnavailable, gin.H{"error": "Matrix service not configured"})
		return
	}

	var req SendMessageRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}

	ctx := c.Request.Context()
	var err error

	if req.HTML != "" {
		err = h.matrixService.SendHTMLMessage(ctx, req.RoomID, req.Message, req.HTML)
	} else {
		err = h.matrixService.SendMessage(ctx, req.RoomID, req.Message)
	}

	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}

	c.JSON(http.StatusOK, gin.H{"success": true})
}

// SendNotificationRequest for sending school notifications
type SendNotificationRequest struct {
	RoomID      string  `json:"room_id" binding:"required"`
	Type        string  `json:"type" binding:"required"` // "absence", "grade", "announcement"
	StudentName string  `json:"student_name,omitempty"`
	Date        string  `json:"date,omitempty"`
	Lesson      int     `json:"lesson,omitempty"`
	Subject     string  `json:"subject,omitempty"`
	GradeType   string  `json:"grade_type,omitempty"`
	Grade       float64 `json:"grade,omitempty"`
	Title       string  `json:"title,omitempty"`
	Content     string  `json:"content,omitempty"`
	TeacherName string  `json:"teacher_name,omitempty"`
}

// SendNotification sends a typed notification (absence, grade, announcement)
func (h *CommunicationHandlers) SendNotification(c *gin.Context) {
	if h.matrixService == nil {
		c.JSON(http.StatusServiceUnavailable, gin.H{"error": "Matrix service not configured"})
		return
	}

	var req SendNotificationRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}

	ctx := c.Request.Context()
	var err error

	switch req.Type {
	case "absence":
		err = h.matrixService.SendAbsenceNotification(ctx, req.RoomID, req.StudentName, req.Date, req.Lesson)
	case "grade":
		err = h.matrixService.SendGradeNotification(ctx, req.RoomID, req.StudentName, req.Subject, req.GradeType, req.Grade)
	case "announcement":
		err = h.matrixService.SendClassAnnouncement(ctx, req.RoomID, req.Title, req.Content, req.TeacherName)
	default:
		c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid notification type. Use: absence, grade, announcement"})
		return
	}

	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}

	c.JSON(http.StatusOK, gin.H{"success": true})
}

// RegisterUserRequest for user registration
type RegisterUserRequest struct {
	Username    string `json:"username" binding:"required"`
	DisplayName string `json:"display_name"`
}

// RegisterMatrixUser registers a new Matrix user
func (h *CommunicationHandlers) RegisterMatrixUser(c *gin.Context) {
	if h.matrixService == nil {
		c.JSON(http.StatusServiceUnavailable, gin.H{"error": "Matrix service not configured"})
		return
	}

	var req RegisterUserRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}

	ctx := c.Request.Context()
	resp, err := h.matrixService.RegisterUser(ctx, req.Username, req.DisplayName)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}

	c.JSON(http.StatusCreated, gin.H{
		"user_id": resp.UserID,
	})
}
