#!/bin/bash

# 🔍 Branch Analyzer - Análise Completa de Branches e PRs
# Autor: Jonas Santos
# Versão: 1.0
# Data: Janeiro 2025

set -e

# Cores para output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
PURPLE='\033[0;35m'
CYAN='\033[0;36m'
WHITE='\033[1;37m'
NC='\033[0m' # No Color

# Emojis
ROCKET="🚀"
CHECK="✅"
WARNING="⚠️"
INFO="ℹ️"
FIRE="🔥"
EYES="👀"
CHART="📊"
FILES="📁"
COMMIT="💻"
MERGE="🔀"
TEST="🧪"
SECURITY="🔒"
PERFORMANCE="⚡"
DOCS="📚"

# Função para exibir cabeçalho
print_header() {
    echo -e "${WHITE}================================================================${NC}"
    echo -e "${CYAN}${ROCKET} BRANCH ANALYZER - Análise Completa de Branch/PR${NC}"
    echo -e "${WHITE}================================================================${NC}"
}

# Função para exibir seção
print_section() {
    echo ""
    echo -e "${YELLOW}$1${NC}"
    echo -e "${WHITE}$(printf '%.0s-' {1..50})${NC}"
}

# Função para exibir erro e sair
error_exit() {
    echo -e "${RED}❌ Erro: $1${NC}" >&2
    exit 1
}

# Função para verificar se é um repositório git
check_git_repo() {
    if ! git rev-parse --git-dir > /dev/null 2>&1; then
        error_exit "Este diretório não é um repositório Git."
    fi
}

# Função para verificar se a branch existe
check_branch_exists() {
    local branch=$1
    if ! git show-ref --verify --quiet refs/remotes/origin/$branch; then
        if ! git show-ref --verify --quiet refs/heads/$branch; then
            error_exit "Branch '$branch' não encontrada localmente nem no remoto."
        fi
    fi
}

# Função para obter informações básicas da branch
get_branch_info() {
    local branch=$1
    local base_branch=${2:-main}
    
    print_section "${INFO} INFORMAÇÕES BÁSICAS"
    
    # Último commit
    local last_commit=$(git log --format="%H" -n 1 origin/$branch 2>/dev/null || git log --format="%H" -n 1 $branch)
    local last_commit_short=$(git log --format="%h" -n 1 origin/$branch 2>/dev/null || git log --format="%h" -n 1 $branch)
    local author=$(git log --format="%an" -n 1 $last_commit)
    local date=$(git log --format="%ad" --date=format:'%d/%m/%Y %H:%M' -n 1 $last_commit)
    local message=$(git log --format="%s" -n 1 $last_commit)
    
    echo -e "${CHECK} ${GREEN}Branch:${NC} $branch"
    echo -e "${CHECK} ${GREEN}Último commit:${NC} $last_commit_short"
    echo -e "${CHECK} ${GREEN}Autor:${NC} $author"
    echo -e "${CHECK} ${GREEN}Data:${NC} $date"
    echo -e "${CHECK} ${GREEN}Mensagem:${NC} $message"
    
    # Status da branch
    local ahead_behind=$(git rev-list --left-right --count origin/$base_branch...origin/$branch 2>/dev/null || echo "0	0")
    local behind=$(echo $ahead_behind | cut -f1)
    local ahead=$(echo $ahead_behind | cut -f2)
    
    echo -e "${CHECK} ${GREEN}Commits à frente de $base_branch:${NC} $ahead"
    echo -e "${CHECK} ${GREEN}Commits atrás de $base_branch:${NC} $behind"
    
    if [ "$behind" -gt 0 ]; then
        echo -e "${WARNING} ${YELLOW}Branch está desatualizada! Considere fazer rebase.${NC}"
    fi
}

# Função para análise de commits
analyze_commits() {
    local branch=$1
    local base_branch=${2:-main}
    
    print_section "${COMMIT} ANÁLISE DE COMMITS"
    
    # Últimos commits da branch
    echo -e "${EYES} ${BLUE}Últimos 10 commits:${NC}"
    git log --oneline origin/$branch -10 2>/dev/null || git log --oneline $branch -10
    
    # Commits únicos da branch
    local unique_commits=$(git rev-list --count origin/$base_branch..origin/$branch 2>/dev/null || git rev-list --count $base_branch..$branch)
    echo -e "\n${CHART} ${GREEN}Commits únicos nesta branch:${NC} $unique_commits"
    
    if [ "$unique_commits" -gt 0 ]; then
        echo -e "\n${EYES} ${BLUE}Commits únicos da branch:${NC}"
        git log --oneline origin/$base_branch..origin/$branch 2>/dev/null || git log --oneline $base_branch..$branch
    fi
}

# Função para análise de arquivos modificados
analyze_files() {
    local branch=$1
    local base_branch=${2:-main}
    
    print_section "${FILES} ANÁLISE DE ARQUIVOS"
    
    # Arquivos modificados
    local modified_files=$(git diff --name-only origin/$base_branch origin/$branch 2>/dev/null || git diff --name-only $base_branch $branch)
    local total_files=$(echo "$modified_files" | wc -l)
    
    if [ -z "$modified_files" ]; then
        echo -e "${INFO} ${BLUE}Nenhum arquivo modificado encontrado.${NC}"
        return
    fi
    
    echo -e "${CHART} ${GREEN}Total de arquivos modificados:${NC} $total_files"
    echo ""
    echo -e "${EYES} ${BLUE}Arquivos modificados:${NC}"
    echo "$modified_files" | while read file; do
        if [ -n "$file" ]; then
            echo "  📄 $file"
        fi
    done
    
    # Estatísticas detalhadas
    echo ""
    echo -e "${CHART} ${GREEN}Estatísticas de mudanças:${NC}"
    git diff --stat origin/$base_branch origin/$branch 2>/dev/null || git diff --stat $base_branch $branch
}

# Função para análise de tipos de arquivo
analyze_file_types() {
    local branch=$1
    local base_branch=${2:-main}
    
    print_section "${CHART} ANÁLISE POR TIPO DE ARQUIVO"
    
    local modified_files=$(git diff --name-only origin/$base_branch origin/$branch 2>/dev/null || git diff --name-only $base_branch $branch)
    
    if [ -z "$modified_files" ]; then
        return
    fi
    
    # Contar por extensão
    echo -e "${EYES} ${BLUE}Distribuição por tipo:${NC}"
    echo "$modified_files" | grep -E '\.' | sed 's/.*\.//' | sort | uniq -c | sort -nr | while read count ext; do
        echo "  📋 .$ext: $count arquivo(s)"
    done
    
    # Arquivos críticos
    echo ""
    echo -e "${SECURITY} ${RED}Arquivos críticos detectados:${NC}"
    
    local critical_found=false
    echo "$modified_files" | while read file; do
        if [ -n "$file" ]; then
            case "$file" in
                package.json|package-lock.json|yarn.lock)
                    echo "  🔴 $file (Dependências)"
                    critical_found=true
                    ;;
                *.config.js|*.config.ts|angular.json|tsconfig*.json)
                    echo "  🟡 $file (Configuração)"
                    critical_found=true
                    ;;
                *.env*|*secret*|*key*|*password*)
                    echo "  🔴 $file (Segurança - ATENÇÃO!)"
                    critical_found=true
                    ;;
                *test*|*spec*|*.test.ts|*.spec.ts)
                    echo "  🟢 $file (Testes)"
                    ;;
                *.md|docs/*|documentation/*)
                    echo "  📘 $file (Documentação)"
                    ;;
            esac
        fi
    done
}

# Função para análise de complexidade
analyze_complexity() {
    local branch=$1
    local base_branch=${2:-main}
    
    print_section "${PERFORMANCE} ANÁLISE DE COMPLEXIDADE"
    
    # Linhas adicionadas/removidas
    local stats=$(git diff --numstat origin/$base_branch origin/$branch 2>/dev/null || git diff --numstat $base_branch $branch)
    
    if [ -z "$stats" ]; then
        echo -e "${INFO} ${BLUE}Nenhuma mudança detectada.${NC}"
        return
    fi
    
    local total_added=0
    local total_removed=0
    local files_count=0
    
    while read added removed file; do
        if [ "$added" != "-" ] && [ "$removed" != "-" ]; then
            total_added=$((total_added + added))
            total_removed=$((total_removed + removed))
            files_count=$((files_count + 1))
        fi
    done <<< "$stats"
    
    echo -e "${CHART} ${GREEN}Linhas adicionadas:${NC} +$total_added"
    echo -e "${CHART} ${RED}Linhas removidas:${NC} -$total_removed"
    echo -e "${CHART} ${BLUE}Total de mudanças:${NC} $((total_added + total_removed))"
    echo -e "${CHART} ${PURPLE}Arquivos afetados:${NC} $files_count"
    
    # Classificação de complexidade
    local total_changes=$((total_added + total_removed))
    if [ $total_changes -lt 50 ]; then
        echo -e "${CHECK} ${GREEN}Complexidade: BAIXA (< 50 linhas)${NC}"
    elif [ $total_changes -lt 200 ]; then
        echo -e "${WARNING} ${YELLOW}Complexidade: MÉDIA (50-200 linhas)${NC}"
    elif [ $total_changes -lt 500 ]; then
        echo -e "${WARNING} ${YELLOW}Complexidade: ALTA (200-500 linhas)${NC}"
    else
        echo -e "${FIRE} ${RED}Complexidade: MUITO ALTA (> 500 linhas)${NC}"
    fi
    
    # Arquivos com mais mudanças
    echo ""
    echo -e "${EYES} ${BLUE}Top 5 arquivos com mais mudanças:${NC}"
    echo "$stats" | awk '$1 != "-" && $2 != "-" {print ($1+$2)" "$3}' | sort -nr | head -5 | while read changes file; do
        echo "  📊 $file: $changes mudanças"
    done
}

# Função para verificar conflitos potenciais
check_potential_conflicts() {
    local branch=$1
    local base_branch=${2:-main}
    
    print_section "${MERGE} VERIFICAÇÃO DE CONFLITOS"
    
    # Tentar fazer um merge dry-run
    echo -e "${INFO} ${BLUE}Verificando possíveis conflitos...${NC}"
    
    # Backup da branch atual
    local current_branch=$(git branch --show-current)
    
    # Criar uma branch temporária para teste
    local temp_branch="temp-merge-test-$(date +%s)"
    
    if git checkout -b $temp_branch origin/$base_branch >/dev/null 2>&1; then
        if git merge --no-commit --no-ff origin/$branch >/dev/null 2>&1; then
            echo -e "${CHECK} ${GREEN}Nenhum conflito detectado! Merge será limpo.${NC}"
            git merge --abort >/dev/null 2>&1
        else
            echo -e "${WARNING} ${RED}Conflitos potenciais detectados!${NC}"
            echo -e "${INFO} ${YELLOW}Arquivos com possíveis conflitos:${NC}"
            git status --porcelain | grep "^UU\|^AA\|^DD" | while read status file; do
                echo "  ⚠️  $file"
            done
            git merge --abort >/dev/null 2>&1
        fi
        
        # Voltar para a branch original e limpar
        git checkout $current_branch >/dev/null 2>&1
        git branch -D $temp_branch >/dev/null 2>&1
    else
        echo -e "${WARNING} ${YELLOW}Não foi possível verificar conflitos automaticamente.${NC}"
    fi
}

# Função para análise de testes
analyze_tests() {
    local branch=$1
    local base_branch=${2:-main}
    
    print_section "${TEST} ANÁLISE DE TESTES"
    
    local modified_files=$(git diff --name-only origin/$base_branch origin/$branch 2>/dev/null || git diff --name-only $base_branch $branch)
    
    if [ -z "$modified_files" ]; then
        return
    fi
    
    # Arquivos de teste modificados
    local test_files=$(echo "$modified_files" | grep -E "\.(test|spec)\.(ts|js)$" || true)
    local test_count=$(echo "$test_files" | grep -v '^$' | wc -l || echo 0)
    
    echo -e "${CHART} ${GREEN}Arquivos de teste modificados:${NC} $test_count"
    
    if [ "$test_count" -gt 0 ]; then
        echo -e "${EYES} ${BLUE}Testes afetados:${NC}"
        echo "$test_files" | while read file; do
            if [ -n "$file" ]; then
                echo "  🧪 $file"
            fi
        done
    fi
    
    # Arquivos de código sem testes correspondentes
    echo ""
    echo -e "${WARNING} ${YELLOW}Verificando cobertura de testes:${NC}"
    
    local code_files=$(echo "$modified_files" | grep -E "\.(ts|js)$" | grep -v -E "\.(test|spec|config|d)\.(ts|js)$" || true)
    echo "$code_files" | while read file; do
        if [ -n "$file" ]; then
            local test_file1="${file%.ts}.spec.ts"
            local test_file2="${file%.ts}.test.ts"
            local test_file3="${file%.js}.spec.js"
            local test_file4="${file%.js}.test.js"
            
            if [ ! -f "$test_file1" ] && [ ! -f "$test_file2" ] && [ ! -f "$test_file3" ] && [ ! -f "$test_file4" ]; then
                echo "  ⚠️  $file (sem teste correspondente)"
            fi
        fi
    done
}

# Função para sugestões de revisão
review_suggestions() {
    local branch=$1
    local base_branch=${2:-main}
    
    print_section "${DOCS} SUGESTÕES PARA REVISÃO"
    
    local modified_files=$(git diff --name-only origin/$base_branch origin/$branch 2>/dev/null || git diff --name-only $base_branch $branch)
    local total_changes=$(git diff --numstat origin/$base_branch origin/$branch 2>/dev/null | awk '{added+=$1; removed+=$2} END {print added+removed}' || echo 0)
    
    echo -e "${EYES} ${BLUE}Pontos importantes para revisar:${NC}"
    
    # Checklist baseado na análise
    echo ""
    echo -e "${CHECK} ${GREEN}CHECKLIST DE REVISÃO:${NC}"
    echo "  📋 Verificar se os commits têm mensagens claras"
    echo "  📋 Validar se as mudanças atendem aos requisitos"
    echo "  📋 Revisar lógica de negócio implementada"
    echo "  📋 Verificar padrões de código e nomenclatura"
    echo "  📋 Validar tratamento de erros"
    echo "  📋 Checar performance das mudanças"
    
    if echo "$modified_files" | grep -q -E "\.(test|spec)\.(ts|js)$"; then
        echo "  📋 Executar testes automatizados"
        echo "  📋 Verificar cobertura de testes"
    else
        echo -e "  ${WARNING} Considerar adicionar testes"
    fi
    
    if echo "$modified_files" | grep -q "package.json"; then
        echo -e "  ${WARNING} Revisar mudanças em dependências"
        echo "  📋 Verificar compatibilidade de versões"
    fi
    
    if echo "$modified_files" | grep -q -E "\.config\.(ts|js)$|angular\.json"; then
        echo -e "  ${WARNING} Revisar mudanças de configuração"
        echo "  📋 Testar em diferentes ambientes"
    fi
    
    if [ "$total_changes" -gt 300 ]; then
        echo -e "  ${WARNING} PR grande - considerar quebrar em partes menores"
        echo "  📋 Revisar com mais cuidado devido ao tamanho"
    fi
    
    echo ""
    echo -e "${PERFORMANCE} ${PURPLE}COMANDOS ÚTEIS PARA REVISÃO:${NC}"
    echo "  git checkout $branch"
    echo "  git diff origin/$base_branch..origin/$branch"
    echo "  git log origin/$base_branch..origin/$branch --oneline"
    echo "  npm test (para executar testes)"
    echo "  npm run build (para verificar build)"
}

# Função para gerar relatório resumido
generate_summary() {
    local branch=$1
    local base_branch=${2:-main}
    
    print_section "${ROCKET} RESUMO EXECUTIVO"
    
    local modified_files=$(git diff --name-only origin/$base_branch origin/$branch 2>/dev/null || git diff --name-only $base_branch $branch)
    local total_files=$(echo "$modified_files" | grep -v '^$' | wc -l || echo 0)
    local total_commits=$(git rev-list --count origin/$base_branch..origin/$branch 2>/dev/null || git rev-list --count $base_branch..$branch)
    local stats=$(git diff --numstat origin/$base_branch origin/$branch 2>/dev/null || git diff --numstat $base_branch $branch)
    local total_added=$(echo "$stats" | awk '$1 != "-" {added+=$1} END {print added+0}')
    local total_removed=$(echo "$stats" | awk '$2 != "-" {removed+=$2} END {print removed+0}')
    local author=$(git log --format="%an" -n 1 origin/$branch 2>/dev/null || git log --format="%an" -n 1 $branch)
    
    echo "┌─────────────────────────────────────────────────┐"
    echo "│                   RESUMO                        │"
    echo "├─────────────────────────────────────────────────┤"
    echo "│ Branch: $branch"
    echo "│ Autor: $author"
    echo "│ Base: $base_branch"
    echo "│ Commits: $total_commits"
    echo "│ Arquivos: $total_files"
    echo "│ Linhas: +$total_added/-$total_removed"
    echo "└─────────────────────────────────────────────────┘"
}

# Função principal
main() {
    local branch_name=""
    local base_branch="main"
    local show_help=false
    
    # Parse dos argumentos
    while [[ $# -gt 0 ]]; do
        case $1 in
            -h|--help)
                show_help=true
                shift
                ;;
            -b|--base)
                base_branch="$2"
                shift 2
                ;;
            *)
                if [ -z "$branch_name" ]; then
                    branch_name="$1"
                fi
                shift
                ;;
        esac
    done
    
    # Mostrar ajuda
    if [ "$show_help" = true ]; then
        echo "🔍 Branch Analyzer - Análise Completa de Branches e PRs"
        echo ""
        echo "Uso: $0 [OPÇÕES] <nome-da-branch>"
        echo ""
        echo "Opções:"
        echo "  -h, --help        Mostra esta ajuda"
        echo "  -b, --base BRANCH Define a branch base para comparação (padrão: main)"
        echo ""
        echo "Exemplos:"
        echo "  $0 feature/checkbox-vehicle"
        echo "  $0 feature/new-feature -b develop"
        echo "  $0 --help"
        exit 0
    fi
    
    # Verificar se branch foi fornecida
    if [ -z "$branch_name" ]; then
        error_exit "Nome da branch é obrigatório. Use -h para ajuda."
    fi
    
    # Verificações iniciais
    check_git_repo
    check_branch_exists "$branch_name"
    
    # Executar análises
    print_header
    get_branch_info "$branch_name" "$base_branch"
    analyze_commits "$branch_name" "$base_branch"
    analyze_files "$branch_name" "$base_branch"
    analyze_file_types "$branch_name" "$base_branch"
    analyze_complexity "$branch_name" "$base_branch"
    check_potential_conflicts "$branch_name" "$base_branch"
    analyze_tests "$branch_name" "$base_branch"
    review_suggestions "$branch_name" "$base_branch"
    generate_summary "$branch_name" "$base_branch"
    
    echo ""
    echo -e "${GREEN}${CHECK} Análise concluída com sucesso!${NC}"
    echo ""
}

# Executar função principal com todos os argumentos
main "$@" 