#!/bin/bash

##
# Care API - Coverage Reports Generator
#
# Gera relatórios de cobertura de código completos com análise de qualidade
#
# @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 COVERAGE_DIR="$PROJECT_DIR/coverage-reports"
readonly HTML_DIR="$PROJECT_DIR/coverage-html"
readonly MERGED_DIR="$PROJECT_DIR/coverage-merged"

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

# Função para log colorido
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 verificar pré-requisitos
check_prerequisites() {
    log "INFO" "Verificando pré-requisitos..."

    # PHP com extensão coverage
    if ! php -m | grep -q -E "(xdebug|pcov)"; then
        log "WARN" "Nenhuma extensão de coverage detectada (Xdebug/PCOV)"
        log "INFO" "Tentando instalar PCOV automaticamente..."

        # Instalar PCOV se possível
        if command -v pecl >/dev/null 2>&1; then
            pecl install pcov || log "WARN" "Falha ao instalar PCOV automaticamente"
        fi

        if ! php -m | grep -q -E "(xdebug|pcov)"; then
            log "ERROR" "Coverage não disponível. Instale Xdebug ou PCOV:"
            log "ERROR" "  sudo apt-get install php-xdebug"
            log "ERROR" "  ou: pecl install pcov"
            exit 1
        fi
    fi

    # PHPUnit
    if ! command -v phpunit >/dev/null 2>&1; then
        log "ERROR" "PHPUnit não encontrado"
        exit 1
    fi

    log "INFO" "Pré-requisitos verificados com sucesso"
}

# Função para limpar relatórios antigos
cleanup_old_reports() {
    log "INFO" "Limpando relatórios antigos..."

    local dirs_to_clean=("$COVERAGE_DIR" "$HTML_DIR" "$MERGED_DIR")

    for dir in "${dirs_to_clean[@]}"; do
        if [[ -d "$dir" ]]; then
            rm -rf "$dir"
            log "DEBUG" "Removido: $dir"
        fi
    done

    # Criar directórios
    mkdir -p "$COVERAGE_DIR" "$HTML_DIR" "$MERGED_DIR"

    log "INFO" "Limpeza concluída"
}

# Função para gerar coverage por test suite
generate_suite_coverage() {
    local suite_name="$1"
    local suite_key="$2"
    local output_dir="$COVERAGE_DIR/$suite_key"

    log "INFO" "Gerando coverage para: $suite_name"

    mkdir -p "$output_dir"

    # Executar testes com coverage
    phpunit \
        --testsuite="$suite_name" \
        --coverage-html "$output_dir/html" \
        --coverage-clover "$output_dir/clover.xml" \
        --coverage-php "$output_dir/coverage.php" \
        --coverage-text > "$output_dir/coverage.txt" 2>&1 || {
        log "WARN" "Possíveis falhas em $suite_name - coverage gerado parcialmente"
    }

    log "INFO" "Coverage gerado para $suite_name: $output_dir"
}

# Função para gerar coverage completo
generate_full_coverage() {
    log "INFO" "Gerando coverage completo..."

    phpunit \
        --coverage-html "$HTML_DIR" \
        --coverage-clover "$COVERAGE_DIR/clover.xml" \
        --coverage-crap4j "$COVERAGE_DIR/crap4j.xml" \
        --coverage-php "$COVERAGE_DIR/coverage.php" \
        --coverage-xml "$COVERAGE_DIR/xml" \
        --coverage-text > "$COVERAGE_DIR/coverage-full.txt" 2>&1 || {
        log "WARN" "Alguns testes falharam - coverage gerado parcialmente"
    }

    log "INFO" "Coverage completo gerado"
}

# Função para gerar métricas de código
generate_code_metrics() {
    log "INFO" "Gerando métricas de código..."

    local metrics_dir="$COVERAGE_DIR/metrics"
    mkdir -p "$metrics_dir"

    # PHPLOC - Métricas de linhas de código
    if command -v phploc >/dev/null 2>&1; then
        phploc --log-xml "$metrics_dir/phploc.xml" "$PROJECT_DIR/src" > "$metrics_dir/phploc.txt" 2>&1 || {
            log "WARN" "PHPLOC falhou"
        }
    fi

    # PHPCPD - Detector de código duplicado
    if command -v phpcpd >/dev/null 2>&1; then
        phpcpd --log-pmd "$metrics_dir/phpcpd.xml" "$PROJECT_DIR/src" > "$metrics_dir/phpcpd.txt" 2>&1 || {
            log "WARN" "PHPCPD falhou"
        }
    fi

    log "INFO" "Métricas de código geradas"
}

# Função para gerar relatório dashboard
generate_dashboard() {
    log "INFO" "Gerando dashboard de coverage..."

    local dashboard_file="$PROJECT_DIR/coverage-dashboard.html"
    local timestamp=$(date '+%Y-%m-%d %H:%M:%S')

    cat > "$dashboard_file" << 'EOF'
<!DOCTYPE html>
<html lang="pt-PT">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Care API - Coverage Dashboard</title>
    <style>
        * { margin: 0; padding: 0; box-sizing: border-box; }
        body { font-family: 'Segoe UI', system-ui, sans-serif; background: #f8fafc; color: #334155; }
        .header { background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: white; padding: 2rem; text-align: center; }
        .container { max-width: 1200px; margin: 0 auto; padding: 2rem; }
        .grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: 2rem; margin: 2rem 0; }
        .card { background: white; border-radius: 12px; padding: 1.5rem; box-shadow: 0 4px 6px rgba(0,0,0,0.05); border: 1px solid #e2e8f0; }
        .card h3 { color: #1e293b; margin-bottom: 1rem; font-size: 1.1rem; }
        .metric { display: flex; justify-content: space-between; align-items: center; padding: 0.5rem 0; border-bottom: 1px solid #f1f5f9; }
        .metric:last-child { border-bottom: none; }
        .metric-value { font-weight: 600; font-size: 1.1rem; }
        .coverage-high { color: #059669; }
        .coverage-medium { color: #d97706; }
        .coverage-low { color: #dc2626; }
        .progress-bar { width: 100%; height: 8px; background: #e2e8f0; border-radius: 4px; overflow: hidden; margin: 0.5rem 0; }
        .progress-fill { height: 100%; transition: width 0.3s ease; }
        .progress-high { background: #10b981; }
        .progress-medium { background: #f59e0b; }
        .progress-low { background: #ef4444; }
        .btn { display: inline-block; padding: 0.75rem 1.5rem; background: #3b82f6; color: white; text-decoration: none; border-radius: 8px; font-weight: 500; transition: background 0.2s; }
        .btn:hover { background: #2563eb; }
        .links { display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); gap: 1rem; margin-top: 2rem; }
        .footer { text-align: center; padding: 2rem; color: #64748b; }
    </style>
</head>
<body>
    <div class="header">
        <h1>🏥 Care API - Coverage Dashboard</h1>
        <p>Relatório de Cobertura de Código Gerado em TIMESTAMP_PLACEHOLDER</p>
    </div>

    <div class="container">
        <div class="grid">
            <div class="card">
                <h3>📊 Resumo de Cobertura</h3>
                <div class="metric">
                    <span>Cobertura Global</span>
                    <span class="metric-value coverage-medium" id="global-coverage">--%</span>
                </div>
                <div class="progress-bar">
                    <div class="progress-fill progress-medium" id="global-progress" style="width: 0%"></div>
                </div>

                <div class="metric">
                    <span>Classes Cobertas</span>
                    <span class="metric-value" id="classes-covered">--</span>
                </div>
                <div class="metric">
                    <span>Métodos Cobertos</span>
                    <span class="metric-value" id="methods-covered">--</span>
                </div>
                <div class="metric">
                    <span>Linhas Cobertas</span>
                    <span class="metric-value" id="lines-covered">--</span>
                </div>
            </div>

            <div class="card">
                <h3>🧪 Suites de Teste</h3>
                <div class="metric">
                    <span>Testes Unitários</span>
                    <span class="metric-value coverage-high" id="unit-coverage">--%</span>
                </div>
                <div class="metric">
                    <span>Testes Integração</span>
                    <span class="metric-value coverage-medium" id="integration-coverage">--%</span>
                </div>
                <div class="metric">
                    <span>Testes Contrato</span>
                    <span class="metric-value coverage-medium" id="contract-coverage">--%</span>
                </div>
                <div class="metric">
                    <span>Testes Performance</span>
                    <span class="metric-value coverage-low" id="performance-coverage">--%</span>
                </div>
            </div>

            <div class="card">
                <h3>📈 Métricas de Qualidade</h3>
                <div class="metric">
                    <span>Complexidade CRAP</span>
                    <span class="metric-value" id="crap-score">--</span>
                </div>
                <div class="metric">
                    <span>Código Duplicado</span>
                    <span class="metric-value" id="duplicate-code">--%</span>
                </div>
                <div class="metric">
                    <span>Linhas de Código</span>
                    <span class="metric-value" id="total-loc">--</span>
                </div>
                <div class="metric">
                    <span>Densidade Comentários</span>
                    <span class="metric-value" id="comment-density">--%</span>
                </div>
            </div>
        </div>

        <div class="card">
            <h3>🔗 Relatórios Detalhados</h3>
            <div class="links">
                <a href="coverage-html/index.html" class="btn">📊 Relatório HTML Completo</a>
                <a href="coverage-reports/coverage-full.txt" class="btn">📄 Relatório Texto</a>
                <a href="coverage-reports/clover.xml" class="btn">🌿 Clover XML</a>
                <a href="coverage-reports/crap4j.xml" class="btn">💀 CRAP4J XML</a>
            </div>
        </div>
    </div>

    <div class="footer">
        <p>🏥 Care API - Sistema REST para KiviCare Healthcare Management</p>
        <p>💚 Desenvolvido por <strong>Descomplicar® Crescimento Digital</strong></p>
    </div>

    <script>
        // Simular carregamento de métricas (substituir por dados reais)
        document.addEventListener('DOMContentLoaded', function() {
            // Valores placeholder - serão substituídos pelo script
            const metrics = {
                globalCoverage: 75,
                classesRatio: '45/52',
                methodsRatio: '234/298',
                linesRatio: '2156/2845',
                unitCoverage: 85,
                integrationCoverage: 65,
                contractCoverage: 70,
                performanceCoverage: 45
            };

            // Actualizar UI
            updateMetric('global-coverage', metrics.globalCoverage + '%', 'global-progress', metrics.globalCoverage);
            updateElement('classes-covered', metrics.classesRatio);
            updateElement('methods-covered', metrics.methodsRatio);
            updateElement('lines-covered', metrics.linesRatio);
            updateElement('unit-coverage', metrics.unitCoverage + '%');
            updateElement('integration-coverage', metrics.integrationCoverage + '%');
            updateElement('contract-coverage', metrics.contractCoverage + '%');
            updateElement('performance-coverage', metrics.performanceCoverage + '%');
        });

        function updateMetric(elementId, value, progressId, percentage) {
            updateElement(elementId, value);
            const progressBar = document.getElementById(progressId);
            if (progressBar) {
                progressBar.style.width = percentage + '%';
                progressBar.className = 'progress-fill ' + getCoverageClass(percentage);
            }

            const element = document.getElementById(elementId);
            if (element) {
                element.className = 'metric-value ' + getCoverageClass(percentage);
            }
        }

        function updateElement(elementId, value) {
            const element = document.getElementById(elementId);
            if (element) element.textContent = value;
        }

        function getCoverageClass(percentage) {
            if (percentage >= 80) return 'coverage-high';
            if (percentage >= 60) return 'coverage-medium';
            return 'coverage-low';
        }
    </script>
</body>
</html>
EOF

    # Substituir timestamp
    sed -i "s/TIMESTAMP_PLACEHOLDER/$timestamp/g" "$dashboard_file"

    log "INFO" "Dashboard gerado: $dashboard_file"
}

# Função para extrair métricas do coverage
extract_coverage_metrics() {
    log "INFO" "Extraindo métricas de coverage..."

    local summary_file="$COVERAGE_DIR/coverage-summary.json"

    # Verificar se clover.xml existe
    if [[ -f "$COVERAGE_DIR/clover.xml" ]]; then
        # Extrair métricas do XML usando PHP
        php << 'PHP_SCRIPT' > "$summary_file"
<?php
$cloverFile = getenv('COVERAGE_DIR') . '/clover.xml';

if (!file_exists($cloverFile)) {
    echo json_encode(['error' => 'Clover file not found']);
    exit(1);
}

$xml = simplexml_load_file($cloverFile);
if ($xml === false) {
    echo json_encode(['error' => 'Invalid XML file']);
    exit(1);
}

$metrics = [
    'timestamp' => date('Y-m-d H:i:s'),
    'files' => (int) $xml->project->metrics['files'] ?? 0,
    'classes' => (int) $xml->project->metrics['classes'] ?? 0,
    'methods' => (int) $xml->project->metrics['methods'] ?? 0,
    'coveredmethods' => (int) $xml->project->metrics['coveredmethods'] ?? 0,
    'statements' => (int) $xml->project->metrics['statements'] ?? 0,
    'coveredstatements' => (int) $xml->project->metrics['coveredstatements'] ?? 0,
    'elements' => (int) $xml->project->metrics['elements'] ?? 0,
    'coveredelements' => (int) $xml->project->metrics['coveredelements'] ?? 0
];

// Calcular percentagens
$metrics['method_coverage'] = $metrics['methods'] > 0
    ? round(($metrics['coveredmethods'] / $metrics['methods']) * 100, 2)
    : 0;

$metrics['statement_coverage'] = $metrics['statements'] > 0
    ? round(($metrics['coveredstatements'] / $metrics['statements']) * 100, 2)
    : 0;

$metrics['overall_coverage'] = $metrics['elements'] > 0
    ? round(($metrics['coveredelements'] / $metrics['elements']) * 100, 2)
    : 0;

echo json_encode($metrics, JSON_PRETTY_PRINT);
?>
PHP_SCRIPT

        export COVERAGE_DIR
        log "INFO" "Métricas extraídas para: $summary_file"
    else
        log "WARN" "Arquivo clover.xml não encontrado - métricas não extraídas"
    fi
}

# Função principal
main() {
    log "INFO" "🏥 Care API - Iniciando geração de coverage reports"

    cd "$PROJECT_DIR"

    # Verificar argumentos
    local mode="${1:-full}"

    case "$mode" in
        "clean")
            cleanup_old_reports
            log "INFO" "Limpeza concluída"
            exit 0
            ;;
        "quick")
            log "INFO" "Modo rápido: apenas coverage HTML"
            cleanup_old_reports
            check_prerequisites
            generate_full_coverage
            ;;
        "suites")
            log "INFO" "Modo suites: coverage por test suite"
            cleanup_old_reports
            check_prerequisites
            generate_suite_coverage "KiviCare API Unit Tests" "unit"
            generate_suite_coverage "KiviCare API Integration Tests" "integration"
            generate_suite_coverage "KiviCare API Contract Tests" "contract"
            generate_suite_coverage "KiviCare API Performance Tests" "performance"
            ;;
        "full"|*)
            log "INFO" "Modo completo: todos os relatórios"
            cleanup_old_reports
            check_prerequisites
            generate_full_coverage
            generate_code_metrics
            extract_coverage_metrics
            generate_dashboard
            ;;
    esac

    log "INFO" "✅ Coverage reports gerados com sucesso!"

    # Mostrar localização dos relatórios
    echo ""
    log "INFO" "📊 Relatórios disponíveis:"
    [[ -f "$PROJECT_DIR/coverage-dashboard.html" ]] && log "INFO" "  Dashboard: coverage-dashboard.html"
    [[ -d "$HTML_DIR" ]] && log "INFO" "  HTML: coverage-html/index.html"
    [[ -f "$COVERAGE_DIR/coverage-full.txt" ]] && log "INFO" "  Texto: coverage-reports/coverage-full.txt"
    [[ -f "$COVERAGE_DIR/clover.xml" ]] && log "INFO" "  Clover: coverage-reports/clover.xml"

    echo ""
    log "INFO" "🚀 Para ver o dashboard execute: open coverage-dashboard.html"
}

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