package roadmap

import (
	"context"
	"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
}

// 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
}
