package usecase

// Score calculates a compliance score from answers and questions.
func Score(audit *Audit, answers []Answer) *ScoreResult {
	result := &ScoreResult{
		AuditID:        audit.ID,
		TotalQuestions: len(audit.Questions),
		ByRegulation:   make(map[string]RegulationScore),
		BySeverity:     make(map[string]SeverityScore),
	}

	answerMap := make(map[string]Answer)
	for _, a := range answers {
		answerMap[a.QuestionID] = a
	}

	for _, q := range audit.Questions {
		a, answered := answerMap[q.ID]
		if !answered {
			continue
		}

		result.Answered++

		passed := isPassed(a)
		switch a.Status {
		case AnswerStatusSkipped:
			result.Skipped++
		default:
			if passed {
				result.Passed++
			} else {
				result.Failed++
			}
		}

		// By regulation
		if q.Regulation != "" {
			rs := result.ByRegulation[q.Regulation]
			rs.Total++
			if passed {
				rs.Passed++
			}
			result.ByRegulation[q.Regulation] = rs
		}

		// By severity
		sev := q.Severity
		if sev == "" {
			sev = "MEDIUM"
		}
		ss := result.BySeverity[sev]
		ss.Total++
		if passed {
			ss.Passed++
		} else {
			ss.Failed++
		}
		result.BySeverity[sev] = ss
	}

	// Calculate scores
	if result.Answered > 0 {
		answerable := result.Answered - result.Skipped
		if answerable > 0 {
			result.ComplianceScore = float64(result.Passed) / float64(answerable) * 100
		}
	}

	for reg, rs := range result.ByRegulation {
		if rs.Total > 0 {
			rs.Score = float64(rs.Passed) / float64(rs.Total) * 100
		}
		result.ByRegulation[reg] = rs
	}

	return result
}

// isPassed checks if an answer represents a pass.
func isPassed(a Answer) bool {
	switch v := a.Value.(type) {
	case bool:
		return v
	case string:
		return v == "yes" || v == "true" || v == "ja"
	case float64:
		return v > 0
	default:
		return false
	}
}
