package roadmap

import (
	"context"
	"encoding/json"
	"fmt"
	"time"

	"github.com/google/uuid"
	"github.com/jackc/pgx/v5"
	"github.com/jackc/pgx/v5/pgxpool"
)

// Store handles roadmap data persistence
type Store struct {
	pool *pgxpool.Pool
}

// NewStore creates a new roadmap store
func NewStore(pool *pgxpool.Pool) *Store {
	return &Store{pool: pool}
}

// ============================================================================
// Roadmap CRUD Operations
// ============================================================================

// CreateRoadmap creates a new roadmap
func (s *Store) CreateRoadmap(ctx context.Context, r *Roadmap) error {
	r.ID = uuid.New()
	r.CreatedAt = time.Now().UTC()
	r.UpdatedAt = r.CreatedAt
	if r.Status == "" {
		r.Status = "draft"
	}
	if r.Version == "" {
		r.Version = "1.0"
	}

	_, err := s.pool.Exec(ctx, `
		INSERT INTO roadmaps (
			id, tenant_id, namespace_id, title, description, version,
			assessment_id, portfolio_id, status,
			total_items, completed_items, progress,
			start_date, target_date,
			created_at, updated_at, created_by
		) VALUES (
			$1, $2, $3, $4, $5, $6,
			$7, $8, $9,
			$10, $11, $12,
			$13, $14,
			$15, $16, $17
		)
	`,
		r.ID, r.TenantID, r.NamespaceID, r.Title, r.Description, r.Version,
		r.AssessmentID, r.PortfolioID, r.Status,
		r.TotalItems, r.CompletedItems, r.Progress,
		r.StartDate, r.TargetDate,
		r.CreatedAt, r.UpdatedAt, r.CreatedBy,
	)

	return err
}

// GetRoadmap retrieves a roadmap by ID
func (s *Store) GetRoadmap(ctx context.Context, id uuid.UUID) (*Roadmap, error) {
	var r Roadmap

	err := s.pool.QueryRow(ctx, `
		SELECT
			id, tenant_id, namespace_id, title, description, version,
			assessment_id, portfolio_id, status,
			total_items, completed_items, progress,
			start_date, target_date,
			created_at, updated_at, created_by
		FROM roadmaps WHERE id = $1
	`, id).Scan(
		&r.ID, &r.TenantID, &r.NamespaceID, &r.Title, &r.Description, &r.Version,
		&r.AssessmentID, &r.PortfolioID, &r.Status,
		&r.TotalItems, &r.CompletedItems, &r.Progress,
		&r.StartDate, &r.TargetDate,
		&r.CreatedAt, &r.UpdatedAt, &r.CreatedBy,
	)

	if err == pgx.ErrNoRows {
		return nil, nil
	}
	if err != nil {
		return nil, err
	}

	return &r, nil
}

// ListRoadmaps lists roadmaps for a tenant with optional filters
func (s *Store) ListRoadmaps(ctx context.Context, tenantID uuid.UUID, filters *RoadmapFilters) ([]Roadmap, error) {
	query := `
		SELECT
			id, tenant_id, namespace_id, title, description, version,
			assessment_id, portfolio_id, status,
			total_items, completed_items, progress,
			start_date, target_date,
			created_at, updated_at, created_by
		FROM roadmaps WHERE tenant_id = $1`

	args := []interface{}{tenantID}
	argIdx := 2

	if filters != nil {
		if filters.Status != "" {
			query += fmt.Sprintf(" AND status = $%d", argIdx)
			args = append(args, filters.Status)
			argIdx++
		}
		if filters.AssessmentID != nil {
			query += fmt.Sprintf(" AND assessment_id = $%d", argIdx)
			args = append(args, *filters.AssessmentID)
			argIdx++
		}
		if filters.PortfolioID != nil {
			query += fmt.Sprintf(" AND portfolio_id = $%d", argIdx)
			args = append(args, *filters.PortfolioID)
			argIdx++
		}
	}

	query += " ORDER BY created_at DESC"

	if filters != nil && filters.Limit > 0 {
		query += fmt.Sprintf(" LIMIT $%d", argIdx)
		args = append(args, filters.Limit)
		argIdx++

		if filters.Offset > 0 {
			query += fmt.Sprintf(" OFFSET $%d", argIdx)
			args = append(args, filters.Offset)
		}
	}

	rows, err := s.pool.Query(ctx, query, args...)
	if err != nil {
		return nil, err
	}
	defer rows.Close()

	var roadmaps []Roadmap
	for rows.Next() {
		var r Roadmap
		err := rows.Scan(
			&r.ID, &r.TenantID, &r.NamespaceID, &r.Title, &r.Description, &r.Version,
			&r.AssessmentID, &r.PortfolioID, &r.Status,
			&r.TotalItems, &r.CompletedItems, &r.Progress,
			&r.StartDate, &r.TargetDate,
			&r.CreatedAt, &r.UpdatedAt, &r.CreatedBy,
		)
		if err != nil {
			return nil, err
		}
		roadmaps = append(roadmaps, r)
	}

	return roadmaps, nil
}

// UpdateRoadmap updates a roadmap
func (s *Store) UpdateRoadmap(ctx context.Context, r *Roadmap) error {
	r.UpdatedAt = time.Now().UTC()

	_, err := s.pool.Exec(ctx, `
		UPDATE roadmaps SET
			title = $2, description = $3, version = $4,
			assessment_id = $5, portfolio_id = $6, status = $7,
			total_items = $8, completed_items = $9, progress = $10,
			start_date = $11, target_date = $12,
			updated_at = $13
		WHERE id = $1
	`,
		r.ID, r.Title, r.Description, r.Version,
		r.AssessmentID, r.PortfolioID, r.Status,
		r.TotalItems, r.CompletedItems, r.Progress,
		r.StartDate, r.TargetDate,
		r.UpdatedAt,
	)

	return err
}

// DeleteRoadmap deletes a roadmap and its items
func (s *Store) DeleteRoadmap(ctx context.Context, id uuid.UUID) error {
	// Delete items first
	_, err := s.pool.Exec(ctx, "DELETE FROM roadmap_items WHERE roadmap_id = $1", id)
	if err != nil {
		return err
	}

	// Delete roadmap
	_, err = s.pool.Exec(ctx, "DELETE FROM roadmaps WHERE id = $1", id)
	return err
}

// ============================================================================
// RoadmapItem CRUD Operations
// ============================================================================

// CreateItem creates a new roadmap item
func (s *Store) CreateItem(ctx context.Context, item *RoadmapItem) error {
	item.ID = uuid.New()
	item.CreatedAt = time.Now().UTC()
	item.UpdatedAt = item.CreatedAt
	if item.Status == "" {
		item.Status = ItemStatusPlanned
	}
	if item.Priority == "" {
		item.Priority = ItemPriorityMedium
	}
	if item.Category == "" {
		item.Category = ItemCategoryTechnical
	}

	dependsOn, _ := json.Marshal(item.DependsOn)
	blockedBy, _ := json.Marshal(item.BlockedBy)
	evidenceReq, _ := json.Marshal(item.EvidenceRequired)
	evidenceProv, _ := json.Marshal(item.EvidenceProvided)

	_, err := s.pool.Exec(ctx, `
		INSERT INTO roadmap_items (
			id, roadmap_id, title, description, category, priority, status,
			control_id, regulation_ref, gap_id,
			effort_days, effort_hours, estimated_cost,
			assignee_id, assignee_name, department,
			planned_start, planned_end, actual_start, actual_end,
			depends_on, blocked_by,
			evidence_required, evidence_provided,
			notes, risk_notes,
			source_row, source_file, sort_order,
			created_at, updated_at
		) VALUES (
			$1, $2, $3, $4, $5, $6, $7,
			$8, $9, $10,
			$11, $12, $13,
			$14, $15, $16,
			$17, $18, $19, $20,
			$21, $22,
			$23, $24,
			$25, $26,
			$27, $28, $29,
			$30, $31
		)
	`,
		item.ID, item.RoadmapID, item.Title, item.Description, string(item.Category), string(item.Priority), string(item.Status),
		item.ControlID, item.RegulationRef, item.GapID,
		item.EffortDays, item.EffortHours, item.EstimatedCost,
		item.AssigneeID, item.AssigneeName, item.Department,
		item.PlannedStart, item.PlannedEnd, item.ActualStart, item.ActualEnd,
		dependsOn, blockedBy,
		evidenceReq, evidenceProv,
		item.Notes, item.RiskNotes,
		item.SourceRow, item.SourceFile, item.SortOrder,
		item.CreatedAt, item.UpdatedAt,
	)

	return err
}

// GetItem retrieves a roadmap item by ID
func (s *Store) GetItem(ctx context.Context, id uuid.UUID) (*RoadmapItem, error) {
	var item RoadmapItem
	var category, priority, status string
	var dependsOn, blockedBy, evidenceReq, evidenceProv []byte

	err := s.pool.QueryRow(ctx, `
		SELECT
			id, roadmap_id, title, description, category, priority, status,
			control_id, regulation_ref, gap_id,
			effort_days, effort_hours, estimated_cost,
			assignee_id, assignee_name, department,
			planned_start, planned_end, actual_start, actual_end,
			depends_on, blocked_by,
			evidence_required, evidence_provided,
			notes, risk_notes,
			source_row, source_file, sort_order,
			created_at, updated_at
		FROM roadmap_items WHERE id = $1
	`, id).Scan(
		&item.ID, &item.RoadmapID, &item.Title, &item.Description, &category, &priority, &status,
		&item.ControlID, &item.RegulationRef, &item.GapID,
		&item.EffortDays, &item.EffortHours, &item.EstimatedCost,
		&item.AssigneeID, &item.AssigneeName, &item.Department,
		&item.PlannedStart, &item.PlannedEnd, &item.ActualStart, &item.ActualEnd,
		&dependsOn, &blockedBy,
		&evidenceReq, &evidenceProv,
		&item.Notes, &item.RiskNotes,
		&item.SourceRow, &item.SourceFile, &item.SortOrder,
		&item.CreatedAt, &item.UpdatedAt,
	)

	if err == pgx.ErrNoRows {
		return nil, nil
	}
	if err != nil {
		return nil, err
	}

	item.Category = ItemCategory(category)
	item.Priority = ItemPriority(priority)
	item.Status = ItemStatus(status)
	json.Unmarshal(dependsOn, &item.DependsOn)
	json.Unmarshal(blockedBy, &item.BlockedBy)
	json.Unmarshal(evidenceReq, &item.EvidenceRequired)
	json.Unmarshal(evidenceProv, &item.EvidenceProvided)

	return &item, nil
}

// ListItems lists items for a roadmap with optional filters
func (s *Store) ListItems(ctx context.Context, roadmapID uuid.UUID, filters *RoadmapItemFilters) ([]RoadmapItem, error) {
	query := `
		SELECT
			id, roadmap_id, title, description, category, priority, status,
			control_id, regulation_ref, gap_id,
			effort_days, effort_hours, estimated_cost,
			assignee_id, assignee_name, department,
			planned_start, planned_end, actual_start, actual_end,
			depends_on, blocked_by,
			evidence_required, evidence_provided,
			notes, risk_notes,
			source_row, source_file, sort_order,
			created_at, updated_at
		FROM roadmap_items WHERE roadmap_id = $1`

	args := []interface{}{roadmapID}
	argIdx := 2

	if filters != nil {
		if filters.Status != "" {
			query += fmt.Sprintf(" AND status = $%d", argIdx)
			args = append(args, string(filters.Status))
			argIdx++
		}
		if filters.Priority != "" {
			query += fmt.Sprintf(" AND priority = $%d", argIdx)
			args = append(args, string(filters.Priority))
			argIdx++
		}
		if filters.Category != "" {
			query += fmt.Sprintf(" AND category = $%d", argIdx)
			args = append(args, string(filters.Category))
			argIdx++
		}
		if filters.AssigneeID != nil {
			query += fmt.Sprintf(" AND assignee_id = $%d", argIdx)
			args = append(args, *filters.AssigneeID)
			argIdx++
		}
		if filters.ControlID != "" {
			query += fmt.Sprintf(" AND control_id = $%d", argIdx)
			args = append(args, filters.ControlID)
			argIdx++
		}
		if filters.SearchQuery != "" {
			query += fmt.Sprintf(" AND (title ILIKE $%d OR description ILIKE $%d)", argIdx, argIdx)
			args = append(args, "%"+filters.SearchQuery+"%")
			argIdx++
		}
	}

	query += " ORDER BY sort_order ASC, priority ASC, created_at ASC"

	if filters != nil && filters.Limit > 0 {
		query += fmt.Sprintf(" LIMIT $%d", argIdx)
		args = append(args, filters.Limit)
		argIdx++

		if filters.Offset > 0 {
			query += fmt.Sprintf(" OFFSET $%d", argIdx)
			args = append(args, filters.Offset)
		}
	}

	rows, err := s.pool.Query(ctx, query, args...)
	if err != nil {
		return nil, err
	}
	defer rows.Close()

	var items []RoadmapItem
	for rows.Next() {
		var item RoadmapItem
		var category, priority, status string
		var dependsOn, blockedBy, evidenceReq, evidenceProv []byte

		err := rows.Scan(
			&item.ID, &item.RoadmapID, &item.Title, &item.Description, &category, &priority, &status,
			&item.ControlID, &item.RegulationRef, &item.GapID,
			&item.EffortDays, &item.EffortHours, &item.EstimatedCost,
			&item.AssigneeID, &item.AssigneeName, &item.Department,
			&item.PlannedStart, &item.PlannedEnd, &item.ActualStart, &item.ActualEnd,
			&dependsOn, &blockedBy,
			&evidenceReq, &evidenceProv,
			&item.Notes, &item.RiskNotes,
			&item.SourceRow, &item.SourceFile, &item.SortOrder,
			&item.CreatedAt, &item.UpdatedAt,
		)
		if err != nil {
			return nil, err
		}

		item.Category = ItemCategory(category)
		item.Priority = ItemPriority(priority)
		item.Status = ItemStatus(status)
		json.Unmarshal(dependsOn, &item.DependsOn)
		json.Unmarshal(blockedBy, &item.BlockedBy)
		json.Unmarshal(evidenceReq, &item.EvidenceRequired)
		json.Unmarshal(evidenceProv, &item.EvidenceProvided)

		items = append(items, item)
	}

	return items, nil
}

// UpdateItem updates a roadmap item
func (s *Store) UpdateItem(ctx context.Context, item *RoadmapItem) error {
	item.UpdatedAt = time.Now().UTC()

	dependsOn, _ := json.Marshal(item.DependsOn)
	blockedBy, _ := json.Marshal(item.BlockedBy)
	evidenceReq, _ := json.Marshal(item.EvidenceRequired)
	evidenceProv, _ := json.Marshal(item.EvidenceProvided)

	_, err := s.pool.Exec(ctx, `
		UPDATE roadmap_items SET
			title = $2, description = $3, category = $4, priority = $5, status = $6,
			control_id = $7, regulation_ref = $8, gap_id = $9,
			effort_days = $10, effort_hours = $11, estimated_cost = $12,
			assignee_id = $13, assignee_name = $14, department = $15,
			planned_start = $16, planned_end = $17, actual_start = $18, actual_end = $19,
			depends_on = $20, blocked_by = $21,
			evidence_required = $22, evidence_provided = $23,
			notes = $24, risk_notes = $25,
			sort_order = $26, updated_at = $27
		WHERE id = $1
	`,
		item.ID, item.Title, item.Description, string(item.Category), string(item.Priority), string(item.Status),
		item.ControlID, item.RegulationRef, item.GapID,
		item.EffortDays, item.EffortHours, item.EstimatedCost,
		item.AssigneeID, item.AssigneeName, item.Department,
		item.PlannedStart, item.PlannedEnd, item.ActualStart, item.ActualEnd,
		dependsOn, blockedBy,
		evidenceReq, evidenceProv,
		item.Notes, item.RiskNotes,
		item.SortOrder, item.UpdatedAt,
	)

	return err
}

// DeleteItem deletes a roadmap item
func (s *Store) DeleteItem(ctx context.Context, id uuid.UUID) error {
	_, err := s.pool.Exec(ctx, "DELETE FROM roadmap_items WHERE id = $1", id)
	return err
}

// BulkCreateItems creates multiple items in a transaction
func (s *Store) BulkCreateItems(ctx context.Context, items []RoadmapItem) error {
	tx, err := s.pool.Begin(ctx)
	if err != nil {
		return err
	}
	defer tx.Rollback(ctx)

	for i := range items {
		item := &items[i]
		item.ID = uuid.New()
		item.CreatedAt = time.Now().UTC()
		item.UpdatedAt = item.CreatedAt

		dependsOn, _ := json.Marshal(item.DependsOn)
		blockedBy, _ := json.Marshal(item.BlockedBy)
		evidenceReq, _ := json.Marshal(item.EvidenceRequired)
		evidenceProv, _ := json.Marshal(item.EvidenceProvided)

		_, err := tx.Exec(ctx, `
			INSERT INTO roadmap_items (
				id, roadmap_id, title, description, category, priority, status,
				control_id, regulation_ref, gap_id,
				effort_days, effort_hours, estimated_cost,
				assignee_id, assignee_name, department,
				planned_start, planned_end, actual_start, actual_end,
				depends_on, blocked_by,
				evidence_required, evidence_provided,
				notes, risk_notes,
				source_row, source_file, sort_order,
				created_at, updated_at
			) VALUES (
				$1, $2, $3, $4, $5, $6, $7,
				$8, $9, $10,
				$11, $12, $13,
				$14, $15, $16,
				$17, $18, $19, $20,
				$21, $22,
				$23, $24,
				$25, $26,
				$27, $28, $29,
				$30, $31
			)
		`,
			item.ID, item.RoadmapID, item.Title, item.Description, string(item.Category), string(item.Priority), string(item.Status),
			item.ControlID, item.RegulationRef, item.GapID,
			item.EffortDays, item.EffortHours, item.EstimatedCost,
			item.AssigneeID, item.AssigneeName, item.Department,
			item.PlannedStart, item.PlannedEnd, item.ActualStart, item.ActualEnd,
			dependsOn, blockedBy,
			evidenceReq, evidenceProv,
			item.Notes, item.RiskNotes,
			item.SourceRow, item.SourceFile, item.SortOrder,
			item.CreatedAt, item.UpdatedAt,
		)
		if err != nil {
			return err
		}
	}

	return tx.Commit(ctx)
}

// ============================================================================
// Import Job Operations
// ============================================================================

// CreateImportJob creates a new import job
func (s *Store) CreateImportJob(ctx context.Context, job *ImportJob) error {
	job.ID = uuid.New()
	job.CreatedAt = time.Now().UTC()
	job.UpdatedAt = job.CreatedAt
	if job.Status == "" {
		job.Status = "pending"
	}

	parsedItems, _ := json.Marshal(job.ParsedItems)

	_, err := s.pool.Exec(ctx, `
		INSERT INTO roadmap_import_jobs (
			id, tenant_id, roadmap_id,
			filename, format, file_size, content_type,
			status, error_message,
			total_rows, valid_rows, invalid_rows, imported_items,
			parsed_items,
			created_at, updated_at, completed_at, created_by
		) VALUES (
			$1, $2, $3,
			$4, $5, $6, $7,
			$8, $9,
			$10, $11, $12, $13,
			$14,
			$15, $16, $17, $18
		)
	`,
		job.ID, job.TenantID, job.RoadmapID,
		job.Filename, string(job.Format), job.FileSize, job.ContentType,
		job.Status, job.ErrorMessage,
		job.TotalRows, job.ValidRows, job.InvalidRows, job.ImportedItems,
		parsedItems,
		job.CreatedAt, job.UpdatedAt, job.CompletedAt, job.CreatedBy,
	)

	return err
}

// GetImportJob retrieves an import job by ID
func (s *Store) GetImportJob(ctx context.Context, id uuid.UUID) (*ImportJob, error) {
	var job ImportJob
	var format string
	var parsedItems []byte

	err := s.pool.QueryRow(ctx, `
		SELECT
			id, tenant_id, roadmap_id,
			filename, format, file_size, content_type,
			status, error_message,
			total_rows, valid_rows, invalid_rows, imported_items,
			parsed_items,
			created_at, updated_at, completed_at, created_by
		FROM roadmap_import_jobs WHERE id = $1
	`, id).Scan(
		&job.ID, &job.TenantID, &job.RoadmapID,
		&job.Filename, &format, &job.FileSize, &job.ContentType,
		&job.Status, &job.ErrorMessage,
		&job.TotalRows, &job.ValidRows, &job.InvalidRows, &job.ImportedItems,
		&parsedItems,
		&job.CreatedAt, &job.UpdatedAt, &job.CompletedAt, &job.CreatedBy,
	)

	if err == pgx.ErrNoRows {
		return nil, nil
	}
	if err != nil {
		return nil, err
	}

	job.Format = ImportFormat(format)
	json.Unmarshal(parsedItems, &job.ParsedItems)

	return &job, nil
}

// UpdateImportJob updates an import job
func (s *Store) UpdateImportJob(ctx context.Context, job *ImportJob) error {
	job.UpdatedAt = time.Now().UTC()

	parsedItems, _ := json.Marshal(job.ParsedItems)

	_, err := s.pool.Exec(ctx, `
		UPDATE roadmap_import_jobs SET
			roadmap_id = $2,
			status = $3, error_message = $4,
			total_rows = $5, valid_rows = $6, invalid_rows = $7, imported_items = $8,
			parsed_items = $9,
			updated_at = $10, completed_at = $11
		WHERE id = $1
	`,
		job.ID, job.RoadmapID,
		job.Status, job.ErrorMessage,
		job.TotalRows, job.ValidRows, job.InvalidRows, job.ImportedItems,
		parsedItems,
		job.UpdatedAt, job.CompletedAt,
	)

	return err
}

// ============================================================================
// Statistics
// ============================================================================

// GetRoadmapStats returns statistics for a roadmap
func (s *Store) GetRoadmapStats(ctx context.Context, roadmapID uuid.UUID) (*RoadmapStats, error) {
	stats := &RoadmapStats{
		ByStatus:     make(map[string]int),
		ByPriority:   make(map[string]int),
		ByCategory:   make(map[string]int),
		ByDepartment: make(map[string]int),
	}

	// Total count
	s.pool.QueryRow(ctx,
		"SELECT COUNT(*) FROM roadmap_items WHERE roadmap_id = $1",
		roadmapID).Scan(&stats.TotalItems)

	// By status
	rows, err := s.pool.Query(ctx,
		"SELECT status, COUNT(*) FROM roadmap_items WHERE roadmap_id = $1 GROUP BY status",
		roadmapID)
	if err == nil {
		defer rows.Close()
		for rows.Next() {
			var status string
			var count int
			rows.Scan(&status, &count)
			stats.ByStatus[status] = count
		}
	}

	// By priority
	rows, err = s.pool.Query(ctx,
		"SELECT priority, COUNT(*) FROM roadmap_items WHERE roadmap_id = $1 GROUP BY priority",
		roadmapID)
	if err == nil {
		defer rows.Close()
		for rows.Next() {
			var priority string
			var count int
			rows.Scan(&priority, &count)
			stats.ByPriority[priority] = count
		}
	}

	// By category
	rows, err = s.pool.Query(ctx,
		"SELECT category, COUNT(*) FROM roadmap_items WHERE roadmap_id = $1 GROUP BY category",
		roadmapID)
	if err == nil {
		defer rows.Close()
		for rows.Next() {
			var category string
			var count int
			rows.Scan(&category, &count)
			stats.ByCategory[category] = count
		}
	}

	// By department
	rows, err = s.pool.Query(ctx,
		"SELECT COALESCE(department, 'Unassigned'), COUNT(*) FROM roadmap_items WHERE roadmap_id = $1 GROUP BY department",
		roadmapID)
	if err == nil {
		defer rows.Close()
		for rows.Next() {
			var dept string
			var count int
			rows.Scan(&dept, &count)
			stats.ByDepartment[dept] = count
		}
	}

	// Overdue items
	s.pool.QueryRow(ctx,
		"SELECT COUNT(*) FROM roadmap_items WHERE roadmap_id = $1 AND planned_end < NOW() AND status NOT IN ('COMPLETED', 'DEFERRED')",
		roadmapID).Scan(&stats.OverdueItems)

	// Upcoming items (next 7 days)
	s.pool.QueryRow(ctx,
		"SELECT COUNT(*) FROM roadmap_items WHERE roadmap_id = $1 AND planned_end BETWEEN NOW() AND NOW() + INTERVAL '7 days' AND status NOT IN ('COMPLETED', 'DEFERRED')",
		roadmapID).Scan(&stats.UpcomingItems)

	// Total effort
	s.pool.QueryRow(ctx,
		"SELECT COALESCE(SUM(effort_days), 0) FROM roadmap_items WHERE roadmap_id = $1",
		roadmapID).Scan(&stats.TotalEffortDays)

	// Progress
	completedCount := stats.ByStatus[string(ItemStatusCompleted)]
	if stats.TotalItems > 0 {
		stats.Progress = (completedCount * 100) / stats.TotalItems
	}

	return stats, nil
}

// UpdateRoadmapProgress recalculates and updates roadmap progress
func (s *Store) UpdateRoadmapProgress(ctx context.Context, roadmapID uuid.UUID) error {
	var total, completed int

	s.pool.QueryRow(ctx,
		"SELECT COUNT(*) FROM roadmap_items WHERE roadmap_id = $1",
		roadmapID).Scan(&total)

	s.pool.QueryRow(ctx,
		"SELECT COUNT(*) FROM roadmap_items WHERE roadmap_id = $1 AND status = 'COMPLETED'",
		roadmapID).Scan(&completed)

	progress := 0
	if total > 0 {
		progress = (completed * 100) / total
	}

	_, err := s.pool.Exec(ctx, `
		UPDATE roadmaps SET
			total_items = $2,
			completed_items = $3,
			progress = $4,
			updated_at = $5
		WHERE id = $1
	`, roadmapID, total, completed, progress, time.Now().UTC())

	return err
}
