package infra

import (
	"fmt"
	"time"
)

// JobFail increments the attempt counter and transitions the job to:
//   - "failed"  when attempts < max_attempts (eligible for retry)
//   - "dead"    when attempts >= max_attempts (no more retries)
//
// errMsg is stored in the error column for debugging.
func JobFail(q *JobQueue, jobID string, errMsg string) error {
	if q == nil {
		return fmt.Errorf("job_fail: queue must not be nil")
	}
	if jobID == "" {
		return fmt.Errorf("job_fail: jobID must not be empty")
	}

	now := time.Now().UTC().Format(time.RFC3339)

	// Atomically increment attempts and decide status.
	query := fmt.Sprintf(`
UPDATE %s
SET
    attempts    = attempts + 1,
    status      = CASE WHEN (attempts + 1) >= max_attempts THEN 'dead' ELSE 'failed' END,
    error       = ?,
    completed_at = ?
WHERE id = ?
`, q.TableName)

	res, err := q.DB.Exec(query, errMsg, now, jobID)
	if err != nil {
		return fmt.Errorf("job_fail: update: %w", err)
	}
	n, _ := res.RowsAffected()
	if n == 0 {
		return fmt.Errorf("job_fail: job %q not found", jobID)
	}
	return nil
}
