package handlers

import (
	"bytes"
	"io"
	"net/http"
	"time"

	"github.com/breakpilot/ai-compliance-sdk/internal/rbac"
	"github.com/breakpilot/ai-compliance-sdk/internal/roadmap"
	"github.com/gin-gonic/gin"
	"github.com/google/uuid"
)

// ============================================================================
// Import Workflow
// ============================================================================

// UploadImport handles file upload for import
// POST /sdk/v1/roadmaps/import/upload
func (h *RoadmapHandlers) UploadImport(c *gin.Context) {
	tenantID := rbac.GetTenantID(c)
	userID := rbac.GetUserID(c)

	// Get file from form
	file, header, err := c.Request.FormFile("file")
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "file is required"})
		return
	}
	defer file.Close()

	// Read file content
	buf := bytes.Buffer{}
	if _, err := io.Copy(&buf, file); err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "failed to read file"})
		return
	}

	// Detect format
	format := roadmap.ImportFormat("")
	filename := header.Filename
	contentType := header.Header.Get("Content-Type")

	// Create import job
	job := &roadmap.ImportJob{
		TenantID:    tenantID,
		Filename:    filename,
		FileSize:    header.Size,
		ContentType: contentType,
		Status:      "pending",
		CreatedBy:   userID,
	}

	if err := h.store.CreateImportJob(c.Request.Context(), job); err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}

	// Parse the file
	job.Status = "parsing"
	h.store.UpdateImportJob(c.Request.Context(), job)

	result, err := h.parser.ParseFile(buf.Bytes(), filename, contentType)
	if err != nil {
		job.Status = "failed"
		job.ErrorMessage = err.Error()
		h.store.UpdateImportJob(c.Request.Context(), job)

		c.JSON(http.StatusBadRequest, gin.H{
			"error":  "failed to parse file",
			"detail": err.Error(),
		})
		return
	}

	// Update job with parsed data
	job.Status = "parsed"
	job.Format = format
	job.TotalRows = result.TotalRows
	job.ValidRows = result.ValidRows
	job.InvalidRows = result.InvalidRows
	job.ParsedItems = result.Items

	h.store.UpdateImportJob(c.Request.Context(), job)

	c.JSON(http.StatusOK, roadmap.ImportParseResponse{
		JobID:       job.ID,
		Status:      job.Status,
		TotalRows:   result.TotalRows,
		ValidRows:   result.ValidRows,
		InvalidRows: result.InvalidRows,
		Items:       result.Items,
		ColumnMap:   buildColumnMap(result.Columns),
	})
}

// GetImportJob returns the status of an import job
// GET /sdk/v1/roadmaps/import/:jobId
func (h *RoadmapHandlers) GetImportJob(c *gin.Context) {
	jobID, err := uuid.Parse(c.Param("jobId"))
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "invalid job ID"})
		return
	}

	job, err := h.store.GetImportJob(c.Request.Context(), jobID)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}
	if job == nil {
		c.JSON(http.StatusNotFound, gin.H{"error": "import job not found"})
		return
	}

	c.JSON(http.StatusOK, gin.H{
		"job":   job,
		"items": job.ParsedItems,
	})
}

// ConfirmImport confirms and executes the import
// POST /sdk/v1/roadmaps/import/:jobId/confirm
func (h *RoadmapHandlers) ConfirmImport(c *gin.Context) {
	jobID, err := uuid.Parse(c.Param("jobId"))
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "invalid job ID"})
		return
	}

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

	job, err := h.store.GetImportJob(c.Request.Context(), jobID)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}
	if job == nil {
		c.JSON(http.StatusNotFound, gin.H{"error": "import job not found"})
		return
	}

	if job.Status != "parsed" {
		c.JSON(http.StatusBadRequest, gin.H{
			"error":  "job is not ready for confirmation",
			"status": job.Status,
		})
		return
	}

	tenantID := rbac.GetTenantID(c)
	userID := rbac.GetUserID(c)

	// Create or use existing roadmap
	var roadmapID uuid.UUID
	if req.RoadmapID != nil {
		roadmapID = *req.RoadmapID
		// Verify roadmap exists
		r, err := h.store.GetRoadmap(c.Request.Context(), roadmapID)
		if err != nil || r == nil {
			c.JSON(http.StatusBadRequest, gin.H{"error": "roadmap not found"})
			return
		}
	} else {
		// Create new roadmap
		title := req.RoadmapTitle
		if title == "" {
			title = "Imported Roadmap - " + job.Filename
		}

		r := &roadmap.Roadmap{
			TenantID:  tenantID,
			Title:     title,
			Status:    "active",
			CreatedBy: userID,
		}

		if err := h.store.CreateRoadmap(c.Request.Context(), r); err != nil {
			c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
			return
		}
		roadmapID = r.ID
	}

	// Determine which rows to import
	selectedRows := make(map[int]bool)
	if len(req.SelectedRows) > 0 {
		for _, row := range req.SelectedRows {
			selectedRows[row] = true
		}
	}

	// Convert parsed items to roadmap items
	var items []roadmap.RoadmapItem
	var importedCount, skippedCount int

	for i, parsed := range job.ParsedItems {
		// Skip invalid items
		if !parsed.IsValid {
			skippedCount++
			continue
		}

		// Skip unselected rows if selection was specified
		if len(selectedRows) > 0 && !selectedRows[parsed.RowNumber] {
			skippedCount++
			continue
		}

		item := roadmap.RoadmapItem{
			RoadmapID:     roadmapID,
			Title:         parsed.Data.Title,
			Description:   parsed.Data.Description,
			Category:      parsed.Data.Category,
			Priority:      parsed.Data.Priority,
			Status:        parsed.Data.Status,
			ControlID:     parsed.Data.ControlID,
			RegulationRef: parsed.Data.RegulationRef,
			GapID:         parsed.Data.GapID,
			EffortDays:    parsed.Data.EffortDays,
			AssigneeName:  parsed.Data.AssigneeName,
			Department:    parsed.Data.Department,
			PlannedStart:  parsed.Data.PlannedStart,
			PlannedEnd:    parsed.Data.PlannedEnd,
			Notes:         parsed.Data.Notes,
			SourceRow:     parsed.RowNumber,
			SourceFile:    job.Filename,
			SortOrder:     i,
		}

		// Apply auto-mappings if requested
		if req.ApplyMappings {
			if parsed.MatchedControl != "" {
				item.ControlID = parsed.MatchedControl
			}
			if parsed.MatchedRegulation != "" {
				item.RegulationRef = parsed.MatchedRegulation
			}
			if parsed.MatchedGap != "" {
				item.GapID = parsed.MatchedGap
			}
		}

		// Set defaults
		if item.Status == "" {
			item.Status = roadmap.ItemStatusPlanned
		}
		if item.Priority == "" {
			item.Priority = roadmap.ItemPriorityMedium
		}
		if item.Category == "" {
			item.Category = roadmap.ItemCategoryTechnical
		}

		items = append(items, item)
		importedCount++
	}

	// Bulk create items
	if len(items) > 0 {
		if err := h.store.BulkCreateItems(c.Request.Context(), items); err != nil {
			c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
			return
		}
	}

	// Update roadmap progress
	h.store.UpdateRoadmapProgress(c.Request.Context(), roadmapID)

	// Update job status
	now := time.Now().UTC()
	job.Status = "completed"
	job.RoadmapID = &roadmapID
	job.ImportedItems = importedCount
	job.CompletedAt = &now
	h.store.UpdateImportJob(c.Request.Context(), job)

	c.JSON(http.StatusOK, roadmap.ImportConfirmResponse{
		RoadmapID:     roadmapID,
		ImportedItems: importedCount,
		SkippedItems:  skippedCount,
		Message:       "Import completed successfully",
	})
}

// ============================================================================
// Helper Functions
// ============================================================================

func buildColumnMap(columns []roadmap.DetectedColumn) map[string]string {
	result := make(map[string]string)
	for _, col := range columns {
		if col.MappedTo != "" {
			result[col.Header] = col.MappedTo
		}
	}
	return result
}
