#!/bin/bash

##
# Care API - Coverage Monitor
#
# Monitora tendências de cobertura e gera alertas
#
# @package Care_API
# @author Descomplicar® Crescimento Digital
# @version 1.0.0
# @since 2025-09-14
##

set -euo pipefail

# Configurações
readonly SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
readonly PROJECT_DIR="$(dirname "$SCRIPT_DIR")"
readonly HISTORY_FILE="$PROJECT_DIR/.coverage-history.json"
readonly THRESHOLD_MIN=70
readonly THRESHOLD_WARN=60
readonly THRESHOLD_CRITICAL=50

# Cores
readonly RED='\033[0;31m'
readonly GREEN='\033[0;32m'
readonly YELLOW='\033[1;33m'
readonly BLUE='\033[0;34m'
readonly NC='\033[0m'

log() {
    local level="$1"
    shift
    local message="$*"
    local timestamp=$(date '+%Y-%m-%d %H:%M:%S')

    case "$level" in
        "INFO")  echo -e "${GREEN}[INFO]${NC}  [$timestamp] $message" ;;
        "WARN")  echo -e "${YELLOW}[WARN]${NC}  [$timestamp] $message" ;;
        "ERROR") echo -e "${RED}[ERROR]${NC} [$timestamp] $message" >&2 ;;
        "DEBUG") echo -e "${BLUE}[DEBUG]${NC} [$timestamp] $message" ;;
    esac
}

# Função para extrair coverage actual
get_current_coverage() {
    local clover_file="$PROJECT_DIR/coverage-reports/clover.xml"

    if [[ ! -f "$clover_file" ]]; then
        log "WARN" "Arquivo clover.xml não encontrado - executando coverage"
        cd "$PROJECT_DIR"
        ./bin/generate-coverage.sh quick >/dev/null 2>&1
    fi

    if [[ -f "$clover_file" ]]; then
        php -r "
            \$xml = simplexml_load_file('$clover_file');
            if (\$xml === false) { echo '0'; exit; }
            \$elements = (int) \$xml->project->metrics['elements'];
            \$covered = (int) \$xml->project->metrics['coveredelements'];
            echo \$elements > 0 ? round((\$covered / \$elements) * 100, 2) : 0;
        "
    else
        echo "0"
    fi
}

# Função para carregar histórico
load_history() {
    if [[ -f "$HISTORY_FILE" ]]; then
        cat "$HISTORY_FILE"
    else
        echo '[]'
    fi
}

# Função para salvar histórico
save_history() {
    local new_entry="$1"
    local history=$(load_history)

    # Manter apenas os últimos 30 registos
    local updated_history=$(echo "$history" | jq --argjson new "$new_entry" '
        . + [$new] | sort_by(.timestamp) | reverse | .[0:30]
    ')

    echo "$updated_history" > "$HISTORY_FILE"
}

# Função para calcular tendência
calculate_trend() {
    local history=$(load_history)
    local count=$(echo "$history" | jq 'length')

    if [[ $count -lt 2 ]]; then
        echo "0"
        return
    fi

    # Calcular diferença entre os 2 últimos registos
    echo "$history" | jq '
        if length >= 2 then
            (.[0].coverage - .[1].coverage) | round * 100
        else
            0
        end
    ' | awk '{print $1/100}'
}

# Função para gerar alerta
generate_alert() {
    local coverage="$1"
    local trend="$2"
    local alert_level
    local alert_message

    if (( $(echo "$coverage < $THRESHOLD_CRITICAL" | bc -l) )); then
        alert_level="CRITICAL"
        alert_message="🚨 COVERAGE CRÍTICO: $coverage% (< $THRESHOLD_CRITICAL%)"
    elif (( $(echo "$coverage < $THRESHOLD_WARN" | bc -l) )); then
        alert_level="WARNING"
        alert_message="⚠️ COVERAGE BAIXO: $coverage% (< $THRESHOLD_WARN%)"
    elif (( $(echo "$coverage < $THRESHOLD_MIN" | bc -l) )); then
        alert_level="INFO"
        alert_message="ℹ️ COVERAGE ABAIXO DO ALVO: $coverage% (< $THRESHOLD_MIN%)"
    else
        alert_level="SUCCESS"
        alert_message="✅ COVERAGE OK: $coverage% (≥ $THRESHOLD_MIN%)"
    fi

    # Adicionar informação de tendência
    if (( $(echo "$trend > 0" | bc -l) )); then
        alert_message="$alert_message 📈 Tendência: +$trend%"
    elif (( $(echo "$trend < 0" | bc -l) )); then
        alert_message="$alert_message 📉 Tendência: $trend%"
    else
        alert_message="$alert_message ➡️ Tendência: estável"
    fi

    log "$alert_level" "$alert_message"

    # Retornar código apropriado
    case "$alert_level" in
        "CRITICAL") return 2 ;;
        "WARNING")  return 1 ;;
        *)          return 0 ;;
    esac
}

# Função para gerar relatório detalhado
generate_detailed_report() {
    local coverage="$1"
    local trend="$2"
    local history=$(load_history)

    echo ""
    log "INFO" "📊 RELATÓRIO DETALHADO DE COVERAGE"
    echo "====================================="

    echo "Current Coverage: $coverage%"
    echo "Trend: $(printf "%.2f" "$trend")%"
    echo "Threshold Min: $THRESHOLD_MIN%"
    echo "Threshold Warn: $THRESHOLD_WARN%"
    echo "Threshold Critical: $THRESHOLD_CRITICAL%"
    echo ""

    log "INFO" "📈 HISTÓRICO RECENTE:"
    echo "$history" | jq -r '
        if length > 0 then
            .[] | "\(.timestamp) - \(.coverage)% (\(.git_commit[0:7]))"
        else
            "Nenhum histórico disponível"
        end
    ' | head -10

    echo ""

    # Análise de classes com baixa cobertura
    local clover_file="$PROJECT_DIR/coverage-reports/clover.xml"
    if [[ -f "$clover_file" ]]; then
        log "INFO" "🎯 CLASSES COM BAIXA COBERTURA:"
        php << 'PHP'
<?php
$cloverFile = getenv('PROJECT_DIR') . '/coverage-reports/clover.xml';
if (!file_exists($cloverFile)) exit;

$xml = simplexml_load_file($cloverFile);
if ($xml === false) exit;

$lowCoverage = [];

foreach ($xml->xpath('//file') as $file) {
    $filename = (string) $file['name'];
    $metrics = $file->metrics;

    if ($metrics) {
        $elements = (int) $metrics['elements'];
        $covered = (int) $metrics['coveredelements'];
        $coverage = $elements > 0 ? ($covered / $elements) * 100 : 0;

        if ($coverage < 70 && $elements > 10) { // Focar em arquivos relevantes
            $lowCoverage[] = [
                'file' => basename($filename),
                'coverage' => round($coverage, 1),
                'uncovered' => $elements - $covered
            ];
        }
    }
}

usort($lowCoverage, function($a, $b) {
    return $a['coverage'] <=> $b['coverage'];
});

foreach (array_slice($lowCoverage, 0, 5) as $item) {
    echo sprintf("  %-40s %5.1f%% (%d não cobertas)\n",
        $item['file'], $item['coverage'], $item['uncovered']);
}
PHP
    fi

    echo ""
}

# Função para integração com webhooks
send_webhook_alert() {
    local coverage="$1"
    local trend="$2"
    local webhook_url="${COVERAGE_WEBHOOK_URL:-}"

    if [[ -z "$webhook_url" ]]; then
        return 0
    fi

    local payload=$(cat << EOF
{
    "project": "Care API",
    "coverage": $coverage,
    "trend": $trend,
    "threshold_min": $THRESHOLD_MIN,
    "timestamp": "$(date -u +%Y-%m-%dT%H:%M:%SZ)",
    "git_commit": "$(git rev-parse HEAD 2>/dev/null || echo 'unknown')",
    "git_branch": "$(git branch --show-current 2>/dev/null || echo 'unknown')"
}
EOF
    )

    if command -v curl >/dev/null 2>&1; then
        curl -X POST \
            -H "Content-Type: application/json" \
            -d "$payload" \
            "$webhook_url" \
            --silent --show-error || {
            log "WARN" "Falha ao enviar webhook"
        }
    fi
}

# Função principal
main() {
    local mode="${1:-monitor}"

    log "INFO" "🏥 Care API - Coverage Monitor iniciado"

    cd "$PROJECT_DIR"

    case "$mode" in
        "monitor")
            # Obter coverage actual
            local current_coverage=$(get_current_coverage)
            log "INFO" "Coverage actual: $current_coverage%"

            # Preparar entrada do histórico
            local git_commit=$(git rev-parse HEAD 2>/dev/null || echo 'unknown')
            local git_branch=$(git branch --show-current 2>/dev/null || echo 'unknown')
            local timestamp=$(date -u +%Y-%m-%dT%H:%M:%SZ)

            local new_entry=$(cat << EOF
{
    "timestamp": "$timestamp",
    "coverage": $current_coverage,
    "git_commit": "$git_commit",
    "git_branch": "$git_branch"
}
EOF
            )

            # Salvar no histórico
            save_history "$new_entry"

            # Calcular tendência
            local trend=$(calculate_trend)
            log "INFO" "Tendência: $(printf "%.2f" "$trend")%"

            # Gerar alertas
            generate_alert "$current_coverage" "$trend"
            local alert_code=$?

            # Enviar webhook se configurado
            send_webhook_alert "$current_coverage" "$trend"

            exit $alert_code
            ;;
        "report")
            local current_coverage=$(get_current_coverage)
            local trend=$(calculate_trend)
            generate_detailed_report "$current_coverage" "$trend"
            ;;
        "history")
            log "INFO" "📊 Histórico de Coverage:"
            load_history | jq -r '.[] | "\(.timestamp) - \(.coverage)% - \(.git_commit[0:7]) (\(.git_branch))"' | head -20
            ;;
        "clean")
            log "INFO" "🧹 Limpando histórico de coverage"
            rm -f "$HISTORY_FILE"
            log "INFO" "Histórico limpo"
            ;;
        *)
            echo "Uso: $0 {monitor|report|history|clean}"
            echo ""
            echo "  monitor  - Monitorizar coverage actual e gerar alertas"
            echo "  report   - Gerar relatório detalhado"
            echo "  history  - Mostrar histórico de coverage"
            echo "  clean    - Limpar histórico"
            echo ""
            echo "Variáveis de ambiente:"
            echo "  COVERAGE_WEBHOOK_URL - URL para webhooks de alerta"
            exit 1
            ;;
    esac
}

# Executar se chamado directamente
if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then
    main "$@"
fi