package handlers

import (
	"fmt"
	"log"
	"net/http"
	"os"
	"os/exec"
	"path/filepath"
	"strings"

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

// ExportHandler converts markdown content to PDF or DOCX via pandoc.
type ExportHandler struct{}

func NewExportHandler() *ExportHandler { return &ExportHandler{} }

type exportRequest struct {
	Content  string `json:"content" binding:"required"`
	Format   string `json:"format" binding:"required"` // "pdf" or "docx"
	Filename string `json:"filename"`                  // optional base name
}

// Convert handles POST /api/v1/export.
// Converts markdown content to the requested format and returns the file.
func (h *ExportHandler) Convert(c *gin.Context) {
	var req exportRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}

	// Validate format
	switch req.Format {
	case "pdf", "docx":
		// ok
	default:
		c.JSON(http.StatusBadRequest, gin.H{"error": "format must be pdf or docx"})
		return
	}

	// Check pandoc availability
	if _, err := exec.LookPath("pandoc"); err != nil {
		c.JSON(http.StatusServiceUnavailable, gin.H{"error": "pandoc is not installed on the server"})
		return
	}

	// Create temp dir for conversion
	tmpDir, err := os.MkdirTemp("", "export-*")
	if err != nil {
		log.Printf("export: failed to create temp dir: %v", err)
		c.JSON(http.StatusInternalServerError, gin.H{"error": "export failed"})
		return
	}
	defer os.RemoveAll(tmpDir)

	// Write markdown to temp file
	inputPath := filepath.Join(tmpDir, "input.md")
	if err := os.WriteFile(inputPath, []byte(req.Content), 0644); err != nil {
		log.Printf("export: failed to write input: %v", err)
		c.JSON(http.StatusInternalServerError, gin.H{"error": "export failed"})
		return
	}

	// Determine output filename
	baseName := "document"
	if req.Filename != "" {
		baseName = strings.TrimSuffix(req.Filename, filepath.Ext(req.Filename))
	}
	outputFile := baseName + "." + req.Format
	outputPath := filepath.Join(tmpDir, outputFile)

	// Build pandoc command
	args := []string{inputPath, "-o", outputPath, "--standalone"}
	if req.Format == "pdf" {
		// Try to use a lightweight PDF engine
		for _, engine := range []string{"weasyprint", "wkhtmltopdf", "pdflatex"} {
			if _, err := exec.LookPath(engine); err == nil {
				args = append(args, "--pdf-engine="+engine)
				break
			}
		}
	}

	cmd := exec.CommandContext(c.Request.Context(), "pandoc", args...)
	cmd.Dir = tmpDir
	if output, err := cmd.CombinedOutput(); err != nil {
		log.Printf("export: pandoc failed: %v\n%s", err, string(output))
		c.JSON(http.StatusInternalServerError, gin.H{
			"error":   "pandoc conversion failed",
			"details": string(output),
		})
		return
	}

	// Serve the file
	contentType := "application/octet-stream"
	switch req.Format {
	case "pdf":
		contentType = "application/pdf"
	case "docx":
		contentType = "application/vnd.openxmlformats-officedocument.wordprocessingml.document"
	}

	c.Header("Content-Disposition", fmt.Sprintf("attachment; filename=%q", outputFile))
	c.File(outputPath)
	c.Header("Content-Type", contentType)
}
