package workshop

import (
	"context"
	"time"

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

// ============================================================================
// Participant Operations
// ============================================================================

// AddParticipant adds a participant to a session
func (s *Store) AddParticipant(ctx context.Context, p *Participant) error {
	p.ID = uuid.New()
	p.JoinedAt = time.Now().UTC()
	p.IsActive = true
	now := p.JoinedAt
	p.LastActiveAt = &now

	_, err := s.pool.Exec(ctx, `
		INSERT INTO workshop_participants (
			id, session_id, user_id,
			name, email, role, department,
			is_active, last_active_at, joined_at, left_at,
			can_edit, can_comment, can_approve
		) VALUES (
			$1, $2, $3,
			$4, $5, $6, $7,
			$8, $9, $10, $11,
			$12, $13, $14
		)
	`,
		p.ID, p.SessionID, p.UserID,
		p.Name, p.Email, string(p.Role), p.Department,
		p.IsActive, p.LastActiveAt, p.JoinedAt, p.LeftAt,
		p.CanEdit, p.CanComment, p.CanApprove,
	)

	return err
}

// GetParticipant retrieves a participant by ID
func (s *Store) GetParticipant(ctx context.Context, id uuid.UUID) (*Participant, error) {
	var p Participant
	var role string

	err := s.pool.QueryRow(ctx, `
		SELECT
			id, session_id, user_id,
			name, email, role, department,
			is_active, last_active_at, joined_at, left_at,
			can_edit, can_comment, can_approve
		FROM workshop_participants WHERE id = $1
	`, id).Scan(
		&p.ID, &p.SessionID, &p.UserID,
		&p.Name, &p.Email, &role, &p.Department,
		&p.IsActive, &p.LastActiveAt, &p.JoinedAt, &p.LeftAt,
		&p.CanEdit, &p.CanComment, &p.CanApprove,
	)

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

	p.Role = ParticipantRole(role)
	return &p, nil
}

// ListParticipants lists participants for a session
func (s *Store) ListParticipants(ctx context.Context, sessionID uuid.UUID) ([]Participant, error) {
	rows, err := s.pool.Query(ctx, `
		SELECT
			id, session_id, user_id,
			name, email, role, department,
			is_active, last_active_at, joined_at, left_at,
			can_edit, can_comment, can_approve
		FROM workshop_participants WHERE session_id = $1
		ORDER BY joined_at ASC
	`, sessionID)
	if err != nil {
		return nil, err
	}
	defer rows.Close()

	var participants []Participant
	for rows.Next() {
		var p Participant
		var role string

		err := rows.Scan(
			&p.ID, &p.SessionID, &p.UserID,
			&p.Name, &p.Email, &role, &p.Department,
			&p.IsActive, &p.LastActiveAt, &p.JoinedAt, &p.LeftAt,
			&p.CanEdit, &p.CanComment, &p.CanApprove,
		)
		if err != nil {
			return nil, err
		}

		p.Role = ParticipantRole(role)
		participants = append(participants, p)
	}

	return participants, nil
}

// UpdateParticipantActivity updates the last active timestamp
func (s *Store) UpdateParticipantActivity(ctx context.Context, id uuid.UUID) error {
	_, err := s.pool.Exec(ctx, `
		UPDATE workshop_participants SET
			last_active_at = NOW(),
			is_active = true
		WHERE id = $1
	`, id)
	return err
}

// LeaveSession marks a participant as having left
func (s *Store) LeaveSession(ctx context.Context, participantID uuid.UUID) error {
	now := time.Now().UTC()
	_, err := s.pool.Exec(ctx, `
		UPDATE workshop_participants SET
			is_active = false,
			left_at = $2
		WHERE id = $1
	`, participantID, now)
	return err
}

// UpdateParticipant updates a participant's information
func (s *Store) UpdateParticipant(ctx context.Context, p *Participant) error {
	_, err := s.pool.Exec(ctx, `
		UPDATE workshop_participants SET
			name = $2,
			email = $3,
			role = $4,
			department = $5,
			can_edit = $6,
			can_comment = $7,
			can_approve = $8
		WHERE id = $1
	`,
		p.ID,
		p.Name, p.Email, string(p.Role), p.Department,
		p.CanEdit, p.CanComment, p.CanApprove,
	)
	return err
}

// ============================================================================
// Comment Operations
// ============================================================================

// AddComment adds a comment to a session
func (s *Store) AddComment(ctx context.Context, c *Comment) error {
	c.ID = uuid.New()
	c.CreatedAt = time.Now().UTC()
	c.UpdatedAt = c.CreatedAt

	_, err := s.pool.Exec(ctx, `
		INSERT INTO workshop_comments (
			id, session_id, participant_id,
			step_number, field_id, response_id,
			text, is_resolved,
			created_at, updated_at
		) VALUES (
			$1, $2, $3, $4, $5, $6, $7, $8, $9, $10
		)
	`,
		c.ID, c.SessionID, c.ParticipantID,
		c.StepNumber, c.FieldID, c.ResponseID,
		c.Text, c.IsResolved,
		c.CreatedAt, c.UpdatedAt,
	)

	return err
}

// GetComments retrieves comments for a session
func (s *Store) GetComments(ctx context.Context, sessionID uuid.UUID, stepNumber *int) ([]Comment, error) {
	query := `
		SELECT
			id, session_id, participant_id,
			step_number, field_id, response_id,
			text, is_resolved,
			created_at, updated_at
		FROM workshop_comments WHERE session_id = $1`

	args := []interface{}{sessionID}
	if stepNumber != nil {
		query += " AND step_number = $2"
		args = append(args, *stepNumber)
	}

	query += " ORDER BY created_at ASC"

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

	var comments []Comment
	for rows.Next() {
		var c Comment
		err := rows.Scan(
			&c.ID, &c.SessionID, &c.ParticipantID,
			&c.StepNumber, &c.FieldID, &c.ResponseID,
			&c.Text, &c.IsResolved,
			&c.CreatedAt, &c.UpdatedAt,
		)
		if err != nil {
			return nil, err
		}
		comments = append(comments, c)
	}

	return comments, nil
}
