package channel

import (
	"database/sql"
	"encoding/json"
	"net/http"

	"git.dustin.coffee/hobokenchicken/dumpsterChat/internal/middleware"
	"github.com/go-chi/chi/v5"
)

type forumTag struct {
	ID      string  `json:"id"`
	Name    string  `json:"name"`
	Emoji   *string `json:"emoji"`
	Color   *string `json:"color"`
	TagID   string  `json:"tag_id"`
}

type forumPost struct {
	threadResponse
	TagIDs []string `json:"tag_ids"`
}

func (h *Handler) registerForumRoutes(r chi.Router) {
	r.Get("/{channelID}/forum-tags", h.ListForumTags)
	r.Post("/{channelID}/forum-tags", h.CreateForumTag)
	r.Delete("/forum-tags/{tagID}", h.DeleteForumTag)
}

// CreateForumTag creates a tag for a forum channel.
func (h *Handler) CreateForumTag(w http.ResponseWriter, r *http.Request) {
	channelID := chi.URLParam(r, "channelID")
	userID, ok := middleware.UserIDFromContext(r.Context())
	if !ok {
		http.Error(w, `{"error":"unauthorized"}`, http.StatusUnauthorized)
		return
	}
	serverID, err := h.serverIDForChannel(r.Context(), channelID)
	if err != nil {
		http.Error(w, `{"error":"channel not found"}`, http.StatusNotFound)
		return
	}
	member, err := h.isMember(r.Context(), userID, serverID)
	if err != nil || !member {
		http.Error(w, `{"error":"forbidden"}`, http.StatusForbidden)
		return
	}

	var req struct {
		Name  string  `json:"name"`
		Emoji *string `json:"emoji"`
		Color *string `json:"color"`
	}
	if err := json.NewDecoder(r.Body).Decode(&req); err != nil || req.Name == "" {
		http.Error(w, `{"error":"invalid request"}`, http.StatusBadRequest)
		return
	}

	var tag forumTag
	err = h.db.QueryRowContext(r.Context(), `
		INSERT INTO forum_tags (channel_id, name, emoji, color)
		VALUES ($1, $2, $3, $4)
		RETURNING id, name, emoji, color
	`, channelID, req.Name, req.Emoji, req.Color).Scan(&tag.ID, &tag.Name, &tag.Emoji, &tag.Color)
	if err != nil {
		http.Error(w, `{"error":"failed to create tag"}`, http.StatusInternalServerError)
		return
	}
	tag.TagID = tag.ID
	w.Header().Set("Content-Type", "application/json")
	w.WriteHeader(http.StatusCreated)
	json.NewEncoder(w).Encode(tag)
}

// ListForumTags lists tags for a forum channel.
func (h *Handler) ListForumTags(w http.ResponseWriter, r *http.Request) {
	channelID := chi.URLParam(r, "channelID")
	userID, ok := middleware.UserIDFromContext(r.Context())
	if !ok {
		http.Error(w, `{"error":"unauthorized"}`, http.StatusUnauthorized)
		return
	}
	serverID, err := h.serverIDForChannel(r.Context(), channelID)
	if err != nil {
		http.Error(w, `{"error":"channel not found"}`, http.StatusNotFound)
		return
	}
	member, err := h.isMember(r.Context(), userID, serverID)
	if err != nil || !member {
		http.Error(w, `{"error":"forbidden"}`, http.StatusForbidden)
		return
	}

	rows, err := h.db.QueryContext(r.Context(), `
		SELECT id, name, emoji, color FROM forum_tags WHERE channel_id = $1 ORDER BY name
	`, channelID)
	if err != nil {
		http.Error(w, `{"error":"server error"}`, http.StatusInternalServerError)
		return
	}
	defer rows.Close()

	tags := make([]forumTag, 0)
	for rows.Next() {
		var t forumTag
		var emoji, color sql.NullString
		if err := rows.Scan(&t.ID, &t.Name, &emoji, &color); err != nil {
			continue
		}
		if emoji.Valid {
			t.Emoji = &emoji.String
		}
		if color.Valid {
			t.Color = &color.String
		}
		t.TagID = t.ID
		tags = append(tags, t)
	}
	w.Header().Set("Content-Type", "application/json")
	json.NewEncoder(w).Encode(tags)
}

// DeleteForumTag deletes a forum tag.
func (h *Handler) DeleteForumTag(w http.ResponseWriter, r *http.Request) {
	tagID := chi.URLParam(r, "tagID")
	userID, ok := middleware.UserIDFromContext(r.Context())
	if !ok {
		http.Error(w, `{"error":"unauthorized"}`, http.StatusUnauthorized)
		return
	}

	var channelID string
	err := h.db.QueryRowContext(r.Context(), `SELECT channel_id FROM forum_tags WHERE id = $1`, tagID).Scan(&channelID)
	if err != nil {
		http.Error(w, `{"error":"tag not found"}`, http.StatusNotFound)
		return
	}
	serverID, err := h.serverIDForChannel(r.Context(), channelID)
	if err != nil {
		http.Error(w, `{"error":"channel not found"}`, http.StatusNotFound)
		return
	}
	member, err := h.isMember(r.Context(), userID, serverID)
	if err != nil || !member {
		http.Error(w, `{"error":"forbidden"}`, http.StatusForbidden)
		return
	}

	_, err = h.db.ExecContext(r.Context(), `DELETE FROM forum_tags WHERE id = $1`, tagID)
	if err != nil {
		http.Error(w, `{"error":"failed to delete tag"}`, http.StatusInternalServerError)
		return
	}
	w.WriteHeader(http.StatusNoContent)
}
