#!/bin/bash
# ================================================================
# OKRFEDEF — Sprint 08: Seguimiento operativo
# CFR, dashboard Champion, notificaciones, retrospectiva
# Ejecutar desde: /home/evolucionamos/public_html/estrategia
# Comando: bash sprint_08_seguimiento.sh
# ================================================================
set -e
echo "========================================="
echo "  OKRFEDEF — Sprint 08: Seguimiento"
echo "========================================="

php artisan make:controller ChampionController
php artisan make:controller RetrospectiveController
php artisan make:notification WeeklyDigestNotification
php artisan make:notification KrRedAlertNotification
php artisan make:notification CheckinReminderNotification

echo ">>> Archivos base creados. Escribiendo lógica..."

# ── 1. CHAMPION CONTROLLER ───────────────────────────────────────
cat > app/Http/Controllers/ChampionController.php << 'PHP'
<?php
namespace App\Http\Controllers;

use App\Jobs\MonthlyAnalysisJob;
use App\Models\AiMessage;
use App\Models\CheckIn;
use App\Models\Cycle;
use App\Models\KeyResult;
use App\Models\Project;
use App\Services\ClaudeService;
use App\Services\OkrService;
use Illuminate\Http\Request;
use Inertia\Inertia;

class ChampionController extends Controller
{
    public function __construct(
        private OkrService    $okr,
        private ClaudeService $claude
    ) {}

    /**
     * Dashboard principal del Champion
     */
    public function dashboard(Project $project, Cycle $cycle)
    {
        $tree    = $this->okr->buildOkrTree($cycle);
        $summary = $this->okr->getCycleScoreSummary($cycle);

        // KRs sin check-in esta semana
        $weekNum = now()->weekOfYear;
        $year    = now()->year;

        $pendingCheckins = KeyResult::whereHas('objective', fn($q) => $q->where('cycle_id', $cycle->id))
            ->where('status', 'active')
            ->whereNotNull('owner_id')
            ->whereDoesntHave('checkIns', fn($q) =>
                $q->where('week_number', $weekNum)->where('year', $year)
            )
            ->with('owner:id,name', 'objective:id,title')
            ->get();

        // Agenda CFR automática (generada por IA si existe)
        $cfragenda = AiMessage::where('project_id', $project->id)
            ->where('module', 'synthesis')
            ->whereJsonContains('context->type', 'cfr_agenda')
            ->latest()->first();

        // Últimos check-ins
        $recentCheckins = CheckIn::whereHas('keyResult.objective', fn($q) =>
                $q->where('cycle_id', $cycle->id))
            ->with(['keyResult:id,title,unit', 'user:id,name'])
            ->orderByDesc('created_at')
            ->take(10)
            ->get();

        return Inertia::render('Champion/Dashboard', [
            'project'         => $project->load('organization'),
            'cycle'           => $cycle,
            'tree'            => $tree,
            'summary'         => $summary,
            'pendingCheckins' => $pendingCheckins,
            'cfragenda'       => $cfragenda?->response,
            'recentCheckins'  => $recentCheckins,
            'weekNum'         => $weekNum,
        ]);
    }

    /**
     * Genera la agenda CFR semanal con IA
     */
    public function generateCfrAgenda(Project $project, Cycle $cycle)
    {
        $summary = $this->okr->getCycleScoreSummary($cycle);
        $tree    = $this->okr->buildOkrTree($cycle);

        $redKrs = collect($tree)->flatMap(fn($obj) =>
            collect($obj['key_results'])->filter(fn($kr) => $kr['traffic_light'] === 'red')
        )->values();

        $yellowKrs = collect($tree)->flatMap(fn($obj) =>
            collect($obj['key_results'])->filter(fn($kr) => $kr['traffic_light'] === 'yellow')
        )->values();

        $prompt = <<<PROMPT
Genera la agenda de la reunión semanal CFR (Conversaciones, Feedback, Reconocimiento) para el equipo de {$project->organization->name}.

ESTADO ACTUAL DEL PLAN:
Score general: {$summary['score']}%
En verde: {$summary['green']} | En amarillo: {$summary['yellow']} | En rojo: {$summary['red']}

KRs EN ROJO (prioridad máxima):
{$redKrs->map(fn($kr) => "- {$kr['title']} ({$kr['score']}%)")->join("\n") ?: 'Ninguno'}

KRs EN AMARILLO (atención):
{$yellowKrs->map(fn($kr) => "- {$kr['title']} ({$kr['score']}%)")->join("\n") ?: 'Ninguno'}

Genera una agenda de reunión de máximo 30 minutos con este formato:

**AGENDA CFR — Semana {{ now()->weekOfYear }}/{{ now()->year }}**
Duración: 30 minutos | Facilitador: OKR Champion

⏱ **00-05 min — Check-in de ánimo** (1 palabra cada uno: ¿cómo llegamos?)
⏱ **05-15 min — KRs críticos** (solo los rojos, 2 min cada uno)
[Lista los KRs rojos con la pregunta que el Champion debe hacer]
⏱ **15-22 min — Alertas amarillas** (60 seg cada uno)
[Lista los KRs amarillos relevantes]
⏱ **22-27 min — Reconocimientos** (celebrar avances)
[Menciona específicamente qué KRs avanzaron bien]
⏱ **27-30 min — Compromisos** (máximo 3, con dueño y fecha)

**PREGUNTA DE CIERRE**: [Una pregunta motivadora para que el equipo se vaya con energía]

Sé específico con los nombres de los KRs. Tono directo y motivador.
PROMPT;

        $response = $this->claude->ask($prompt, '', 800);

        if ($response) {
            AiMessage::create([
                'project_id' => $project->id,
                'module'     => 'synthesis',
                'context'    => ['type' => 'cfr_agenda', 'cycle_id' => $cycle->id, 'week' => now()->weekOfYear],
                'prompt'     => $prompt,
                'response'   => $response,
                'model'      => config('services.anthropic.model'),
                'trigger'    => 'proactive',
            ]);
        }

        return response()->json(['agenda' => $response]);
    }

    /**
     * Vista de la reunión CFR en curso
     */
    public function cfr(Project $project, Cycle $cycle)
    {
        $summary = $this->okr->getCycleScoreSummary($cycle);
        $tree    = $this->okr->buildOkrTree($cycle);

        $latestAgenda = AiMessage::where('project_id', $project->id)
            ->where('module', 'synthesis')
            ->whereJsonContains('context->type', 'cfr_agenda')
            ->latest()->first();

        return Inertia::render('Champion/Cfr', [
            'project' => $project->load('organization'),
            'cycle'   => $cycle,
            'summary' => $summary,
            'tree'    => $tree,
            'agenda'  => $latestAgenda?->response,
        ]);
    }
}
PHP

# ── 2. RETROSPECTIVE CONTROLLER ──────────────────────────────────
cat > app/Http/Controllers/RetrospectiveController.php << 'PHP'
<?php
namespace App\Http\Controllers;

use App\Jobs\QuarterlyReportJob;
use App\Models\AiMessage;
use App\Models\Cycle;
use App\Models\Project;
use App\Services\OkrService;
use Illuminate\Http\Request;
use Inertia\Inertia;

class RetrospectiveController extends Controller
{
    public function __construct(private OkrService $okr) {}

    public function index(Project $project, Cycle $cycle)
    {
        $summary = $this->okr->getCycleScoreSummary($cycle);
        $tree    = $this->okr->buildOkrTree($cycle);

        $latestReport = AiMessage::where('project_id', $project->id)
            ->where('module', 'quarterly')
            ->latest()->first();

        $previousCycles = Cycle::where('project_id', $project->id)
            ->where('id', '!=', $cycle->id)
            ->orderByDesc('year')->orderByDesc('quarter')
            ->take(3)->get();

        return Inertia::render('Champion/Retrospective', [
            'project'        => $project->load('organization'),
            'cycle'          => $cycle,
            'summary'        => $summary,
            'tree'           => $tree,
            'latestReport'   => $latestReport?->response,
            'previousCycles' => $previousCycles,
        ]);
    }

    public function generate(Project $project, Cycle $cycle)
    {
        QuarterlyReportJob::dispatch($project, $cycle);
        return response()->json(['message' => 'Generando retrospectiva... llegará en segundos.']);
    }
}
PHP

# ── 3. NOTIFICACIONES ────────────────────────────────────────────
cat > app/Notifications/WeeklyDigestNotification.php << 'PHP'
<?php
namespace App\Notifications;

use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Notifications\Messages\MailMessage;
use Illuminate\Notifications\Notification;

class WeeklyDigestNotification extends Notification implements ShouldQueue
{
    use Queueable;

    public function __construct(
        public string $projectName,
        public array  $summary,
        public string $dashboardUrl
    ) {}

    public function via(): array { return ['mail']; }

    public function toMail($notifiable): MailMessage
    {
        $scorePercent = round($this->summary['score'] * 100);
        $emoji = $scorePercent >= 70 ? '🟢' : ($scorePercent >= 40 ? '🟡' : '🔴');

        return (new MailMessage)
            ->subject("📊 Resumen semanal — {$this->projectName}")
            ->greeting("Hola {$notifiable->name},")
            ->line("Aquí está el resumen del plan estratégico de esta semana.")
            ->line("{$emoji} **Score general: {$scorePercent}%**")
            ->line("✅ En verde: {$this->summary['green']} objetivos")
            ->line("⚠️ En amarillo: {$this->summary['yellow']} objetivos")
            ->line("🔴 En rojo: {$this->summary['red']} objetivos")
            ->action('Ver dashboard completo', $this->dashboardUrl)
            ->line('Recuerda ingresar tu check-in semanal si aún no lo has hecho.');
    }
}
PHP

cat > app/Notifications/KrRedAlertNotification.php << 'PHP'
<?php
namespace App\Notifications;

use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Notifications\Messages\MailMessage;
use Illuminate\Notifications\Notification;

class KrRedAlertNotification extends Notification implements ShouldQueue
{
    use Queueable;

    public function __construct(
        public string $krTitle,
        public float  $score,
        public string $projectName,
        public string $checkinUrl
    ) {}

    public function via(): array { return ['mail']; }

    public function toMail($notifiable): MailMessage
    {
        return (new MailMessage)
            ->subject("🔴 Alerta: KR en riesgo — {$this->projectName}")
            ->greeting("Hola {$notifiable->name},")
            ->line("Tu Key Result está en zona roja y requiere atención.")
            ->line("**KR:** {$this->krTitle}")
            ->line("**Score actual:** " . round($this->score * 100) . "%")
            ->action('Ingresar check-in', $this->checkinUrl)
            ->line('Un check-in actualizado ayuda al equipo a entender el estado y tomar decisiones.');
    }
}
PHP

cat > app/Notifications/CheckinReminderNotification.php << 'PHP'
<?php
namespace App\Notifications;

use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Notifications\Messages\MailMessage;
use Illuminate\Notifications\Notification;

class CheckinReminderNotification extends Notification implements ShouldQueue
{
    use Queueable;

    public function __construct(
        public string $projectName,
        public int    $pendingCount,
        public string $checkinUrl
    ) {}

    public function via(): array { return ['mail']; }

    public function toMail($notifiable): MailMessage
    {
        return (new MailMessage)
            ->subject("⏰ Recordatorio check-in — {$this->projectName}")
            ->greeting("Hola {$notifiable->name},")
            ->line("Tienes {$this->pendingCount} Key Result(s) pendiente(s) de check-in esta semana.")
            ->action('Ingresar check-in ahora', $this->checkinUrl)
            ->line('El check-in toma menos de 2 minutos y mantiene informado a todo el equipo.');
    }
}
PHP

# ── 4. CONSOLE SCHEDULER ─────────────────────────────────────────
cat >> app/Console/Kernel.php << 'PHP'
// NOTA: Si no existe Kernel.php en Laravel 13, agregar al bootstrap/app.php
// Las tareas programadas van en routes/console.php
PHP

cat >> routes/console.php << 'PHP'

use Illuminate\Support\Facades\Schedule;
use App\Jobs\WeeklyDigestJob;
use App\Jobs\MonthlyAnalysisJob;

// Recordatorio check-in: lunes 8am
Schedule::call(function () {
    \App\Models\Project::where('status', 'active')->each(function ($project) {
        $cycle = $project->cycles()->where('status', 'active')->latest()->first();
        if (!$cycle) return;
        $weekNum = now()->weekOfYear;
        $year    = now()->year;
        \App\Models\KeyResult::whereHas('objective', fn($q) => $q->where('cycle_id', $cycle->id))
            ->where('status', 'active')
            ->whereNotNull('owner_id')
            ->whereDoesntHave('checkIns', fn($q) => $q->where('week_number', $weekNum)->where('year', $year))
            ->with('owner')
            ->get()
            ->each(function ($kr) use ($project, $cycle) {
                if ($kr->owner) {
                    $kr->owner->notify(new \App\Notifications\CheckinReminderNotification(
                        $project->name,
                        1,
                        route('okr.checkin', [$project->id, $cycle->id])
                    ));
                }
            });
    });
})->weeklyOn(1, '08:00')->name('checkin-reminder');
PHP

# ── 5. RUTAS ─────────────────────────────────────────────────────
cat >> routes/web.php << 'PHP'

// ── Champion y Retrospectiva Routes ──────────────────────────────
use App\Http\Controllers\ChampionController;
use App\Http\Controllers\RetrospectiveController;

Route::middleware(['auth', 'verified'])->prefix('projects/{project}')->group(function () {
    Route::get('/cycles/{cycle}/champion',         [ChampionController::class, 'dashboard'])->name('champion.dashboard');
    Route::get('/cycles/{cycle}/champion/cfr',     [ChampionController::class, 'cfr'])->name('champion.cfr');
    Route::post('/cycles/{cycle}/champion/agenda', [ChampionController::class, 'generateCfrAgenda'])->name('champion.agenda');
    Route::get('/cycles/{cycle}/retrospective',    [RetrospectiveController::class, 'index'])->name('retro.index');
    Route::post('/cycles/{cycle}/retrospective',   [RetrospectiveController::class, 'generate'])->name('retro.generate');
});
PHP

# ── 6. VISTAS VUE ────────────────────────────────────────────────
mkdir -p resources/js/Pages/Champion

cat > resources/js/Pages/Champion/Dashboard.vue << 'VUE'
<script setup>
import { ref } from 'vue'
import { router } from '@inertiajs/vue3'
import AppLayout from '@/Layouts/AppLayout.vue'
import AiChatPanel from '@/Components/AiChatPanel.vue'
import axios from 'axios'

const props = defineProps({
    project: Object,
    cycle: Object,
    tree: Array,
    summary: Object,
    pendingCheckins: Array,
    cfragenda: String,
    recentCheckins: Array,
    weekNum: Number,
})

const agenda = ref(props.cfragenda)
const generatingAgenda = ref(false)

const generateAgenda = async () => {
    generatingAgenda.value = true
    try {
        const res = await axios.post(route('champion.agenda', [props.project.id, props.cycle.id]))
        agenda.value = res.data.agenda
    } finally { generatingAgenda.value = false }
}

const scoreBar = (s) => Math.round(s * 100)
const tlColor = (tl) => tl === 'green' ? 'bg-green-500' : tl === 'yellow' ? 'bg-yellow-500' : 'bg-red-500'
const scoreTextColor = (s) => s >= 0.70 ? 'text-green-600' : s >= 0.40 ? 'text-yellow-600' : 'text-red-600'
</script>

<template>
    <AppLayout :title="`Champion Dashboard — ${project.name}`">
        <div class="max-w-5xl mx-auto px-4 py-6">

            <div class="flex justify-between items-center mb-6">
                <div>
                    <h1 class="text-2xl font-bold text-gray-900">Dashboard OKR Champion</h1>
                    <p class="text-gray-500">Semana {{ weekNum }} · Q{{ cycle.quarter }} {{ cycle.year }}</p>
                </div>
                <div class="flex gap-2">
                    <a :href="route('champion.cfr', [project.id, cycle.id])"
                       class="bg-blue-600 text-white px-4 py-2 rounded-xl text-sm font-medium hover:bg-blue-700">
                        Facilitar CFR →
                    </a>
                    <a :href="route('retro.index', [project.id, cycle.id])"
                       class="bg-gray-200 text-gray-700 px-4 py-2 rounded-xl text-sm font-medium hover:bg-gray-300">
                        Retrospectiva
                    </a>
                </div>
            </div>

            <div class="grid grid-cols-3 gap-6">
                <div class="col-span-2 space-y-4">

                    <!-- Scores -->
                    <div class="grid grid-cols-4 gap-3">
                        <div class="bg-white rounded-xl shadow p-4 text-center">
                            <div class="text-3xl font-black" :class="scoreTextColor(summary.score)">{{ scoreBar(summary.score) }}%</div>
                            <div class="text-xs text-gray-500">Score</div>
                        </div>
                        <div class="bg-green-50 rounded-xl shadow p-4 text-center">
                            <div class="text-3xl font-black text-green-600">{{ summary.green }}</div>
                            <div class="text-xs text-green-600">🟢</div>
                        </div>
                        <div class="bg-yellow-50 rounded-xl shadow p-4 text-center">
                            <div class="text-3xl font-black text-yellow-600">{{ summary.yellow }}</div>
                            <div class="text-xs text-yellow-600">🟡</div>
                        </div>
                        <div class="bg-red-50 rounded-xl shadow p-4 text-center">
                            <div class="text-3xl font-black text-red-600">{{ summary.red }}</div>
                            <div class="text-xs text-red-600">🔴</div>
                        </div>
                    </div>

                    <!-- Check-ins pendientes -->
                    <div v-if="pendingCheckins.length" class="bg-orange-50 border border-orange-200 rounded-2xl p-4">
                        <h2 class="text-sm font-semibold text-orange-700 mb-3">⏰ Check-ins pendientes esta semana</h2>
                        <div class="space-y-2">
                            <div v-for="kr in pendingCheckins" :key="kr.id"
                                 class="bg-white rounded-xl p-3 flex justify-between items-center">
                                <div>
                                    <p class="text-sm font-medium">{{ kr.title }}</p>
                                    <p class="text-xs text-gray-400">{{ kr.owner?.name || 'Sin owner' }} · {{ kr.objective?.title }}</p>
                                </div>
                                <div class="w-2 h-2 rounded-full" :class="tlColor(kr.traffic_light)"></div>
                            </div>
                        </div>
                    </div>

                    <!-- OKR Tree compacto -->
                    <div class="space-y-2">
                        <div v-for="obj in tree" :key="obj.id" class="bg-white rounded-xl shadow p-4">
                            <div class="flex justify-between items-center mb-2">
                                <h3 class="font-medium text-sm text-gray-800">{{ obj.title }}</h3>
                                <span class="text-sm font-bold" :class="scoreTextColor(obj.score)">{{ scoreBar(obj.score) }}%</span>
                            </div>
                            <div class="space-y-1">
                                <div v-for="kr in obj.key_results" :key="kr.id" class="flex items-center gap-2">
                                    <div class="w-1.5 h-1.5 rounded-full shrink-0" :class="tlColor(kr.traffic_light)"></div>
                                    <span class="text-xs text-gray-600 flex-1 truncate">{{ kr.title }}</span>
                                    <span class="text-xs font-bold" :class="scoreTextColor(kr.score)">{{ scoreBar(kr.score) }}%</span>
                                </div>
                            </div>
                        </div>
                    </div>
                </div>

                <!-- Panel lateral -->
                <div class="space-y-4">

                    <!-- Agenda CFR -->
                    <div class="bg-white rounded-2xl shadow p-4">
                        <div class="flex justify-between items-center mb-3">
                            <h2 class="text-sm font-semibold text-gray-700">Agenda CFR</h2>
                            <button @click="generateAgenda" :disabled="generatingAgenda"
                                    class="text-xs bg-blue-600 text-white px-2 py-1 rounded disabled:bg-gray-300">
                                {{ generatingAgenda ? '...' : '↺ Generar' }}
                            </button>
                        </div>
                        <div v-if="agenda" class="text-xs text-gray-600 whitespace-pre-line leading-relaxed max-h-48 overflow-y-auto">
                            {{ agenda }}
                        </div>
                        <div v-else class="text-xs text-gray-400 italic text-center py-4">
                            Haz clic en "Generar" para crear la agenda de la reunión
                        </div>
                    </div>

                    <!-- Últimos check-ins -->
                    <div class="bg-white rounded-2xl shadow p-4">
                        <h2 class="text-sm font-semibold text-gray-700 mb-3">Últimos check-ins</h2>
                        <div class="space-y-2">
                            <div v-for="ci in recentCheckins" :key="ci.id" class="text-xs">
                                <div class="flex justify-between">
                                    <span class="text-gray-700 truncate">{{ ci.key_result?.title }}</span>
                                    <span class="font-bold text-gray-900 ml-2">{{ ci.value }}</span>
                                </div>
                                <div class="text-gray-400">{{ ci.user?.name }}</div>
                            </div>
                        </div>
                    </div>

                    <!-- Chat IA -->
                    <AiChatPanel :project="project" compact placeholder="Pregunta al Champion..." />
                </div>
            </div>
        </div>
    </AppLayout>
</template>
VUE

cat > resources/js/Pages/Champion/Cfr.vue << 'VUE'
<script setup>
import { ref } from 'vue'
import AppLayout from '@/Layouts/AppLayout.vue'

const props = defineProps({
    project: Object,
    cycle: Object,
    summary: Object,
    tree: Array,
    agenda: String,
})

const notes = ref('')
const commitments = ref([{ text: '', owner: '', due: '' }])

const addCommitment = () => commitments.value.push({ text: '', owner: '', due: '' })
const scoreBar = (s) => Math.round(s * 100)
const tlColor = (tl) => tl === 'green' ? 'bg-green-500' : tl === 'yellow' ? 'bg-yellow-500' : 'bg-red-500'
</script>

<template>
    <AppLayout :title="`Reunión CFR — Q${cycle.quarter} ${cycle.year}`">
        <div class="max-w-4xl mx-auto px-4 py-6">

            <div class="mb-6">
                <h1 class="text-2xl font-bold">Reunión CFR</h1>
                <p class="text-gray-500">Conversación · Feedback · Reconocimiento</p>
                <p class="text-sm text-gray-400 mt-1">Q{{ cycle.quarter }} {{ cycle.year }} · {{ project.organization?.name }}</p>
            </div>

            <div class="grid grid-cols-3 gap-6">

                <!-- Agenda -->
                <div class="col-span-2 space-y-4">
                    <div v-if="agenda" class="bg-white rounded-2xl shadow p-5">
                        <h2 class="text-sm font-semibold text-gray-600 uppercase mb-3">Agenda generada por IA</h2>
                        <div class="text-sm text-gray-700 whitespace-pre-line leading-relaxed">{{ agenda }}</div>
                    </div>

                    <!-- KRs para revisar -->
                    <div class="bg-white rounded-2xl shadow p-5">
                        <h2 class="text-sm font-semibold text-gray-600 uppercase mb-3">Estado KRs</h2>
                        <div class="space-y-2">
                            <div v-for="obj in tree" :key="obj.id">
                                <div v-for="kr in obj.key_results.filter(k => k.traffic_light !== 'green')" :key="kr.id"
                                     :class="['rounded-xl p-3 flex items-center gap-3', kr.traffic_light === 'red' ? 'bg-red-50' : 'bg-yellow-50']">
                                    <div class="w-2 h-2 rounded-full shrink-0" :class="tlColor(kr.traffic_light)"></div>
                                    <div class="flex-1">
                                        <p class="text-sm font-medium">{{ kr.title }}</p>
                                        <p class="text-xs text-gray-400">{{ kr.owner }} · {{ kr.current }}/{{ kr.target }} {{ kr.unit }}</p>
                                    </div>
                                    <span class="text-sm font-bold">{{ scoreBar(kr.score) }}%</span>
                                </div>
                            </div>
                        </div>
                    </div>

                    <!-- Compromisos -->
                    <div class="bg-white rounded-2xl shadow p-5">
                        <h2 class="text-sm font-semibold text-gray-600 uppercase mb-3">Compromisos de la semana</h2>
                        <div class="space-y-2 mb-3">
                            <div v-for="(c, i) in commitments" :key="i" class="grid grid-cols-3 gap-2">
                                <input v-model="c.text" placeholder="Compromiso..." class="col-span-1 border border-gray-300 rounded-lg p-2 text-sm" />
                                <input v-model="c.owner" placeholder="Responsable" class="border border-gray-300 rounded-lg p-2 text-sm" />
                                <input v-model="c.due" type="date" class="border border-gray-300 rounded-lg p-2 text-sm" />
                            </div>
                        </div>
                        <button @click="addCommitment" class="text-sm text-blue-600 hover:underline">+ Agregar compromiso</button>
                    </div>

                    <!-- Notas -->
                    <div class="bg-white rounded-2xl shadow p-5">
                        <h2 class="text-sm font-semibold text-gray-600 uppercase mb-3">Notas de la reunión</h2>
                        <textarea v-model="notes" rows="4" placeholder="Decisiones tomadas, puntos importantes..."
                                  class="w-full border border-gray-300 rounded-xl p-3 text-sm resize-none"></textarea>
                    </div>
                </div>

                <!-- Panel lateral: semáforo -->
                <div>
                    <div class="bg-white rounded-2xl shadow p-4 sticky top-6">
                        <h2 class="text-sm font-semibold text-gray-600 uppercase mb-3">Semáforo</h2>
                        <div class="space-y-2 text-center">
                            <div class="bg-green-50 rounded-xl p-3">
                                <div class="text-3xl font-black text-green-600">{{ summary.green }}</div>
                                <div class="text-xs text-green-600">Verde ≥70%</div>
                            </div>
                            <div class="bg-yellow-50 rounded-xl p-3">
                                <div class="text-3xl font-black text-yellow-600">{{ summary.yellow }}</div>
                                <div class="text-xs text-yellow-600">Amarillo</div>
                            </div>
                            <div class="bg-red-50 rounded-xl p-3">
                                <div class="text-3xl font-black text-red-600">{{ summary.red }}</div>
                                <div class="text-xs text-red-600">Rojo &lt;40%</div>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </AppLayout>
</template>
VUE

cat > resources/js/Pages/Champion/Retrospective.vue << 'VUE'
<script setup>
import { ref } from 'vue'
import { router } from '@inertiajs/vue3'
import AppLayout from '@/Layouts/AppLayout.vue'
import axios from 'axios'

const props = defineProps({
    project: Object,
    cycle: Object,
    summary: Object,
    tree: Array,
    latestReport: String,
    previousCycles: Array,
})

const report = ref(props.latestReport)
const generating = ref(false)

const generate = async () => {
    generating.value = true
    try {
        await axios.post(route('retro.generate', [props.project.id, props.cycle.id]))
        // El reporte llegará via WebSocket
    } finally { generating.value = false }
}

const scoreBar = (s) => Math.round(s * 100)
</script>

<template>
    <AppLayout :title="`Retrospectiva Q${cycle.quarter} ${cycle.year}`">
        <div class="max-w-4xl mx-auto px-4 py-6">

            <div class="flex justify-between items-center mb-6">
                <div>
                    <h1 class="text-2xl font-bold">Retrospectiva Trimestral</h1>
                    <p class="text-gray-500">Q{{ cycle.quarter }} {{ cycle.year }} · {{ project.organization?.name }}</p>
                </div>
                <button @click="generate" :disabled="generating"
                        class="bg-purple-600 text-white px-4 py-2 rounded-xl text-sm font-medium hover:bg-purple-700 disabled:bg-gray-300">
                    {{ generating ? 'Generando...' : '↺ Generar con IA' }}
                </button>
            </div>

            <!-- Score final del ciclo -->
            <div class="grid grid-cols-4 gap-4 mb-6">
                <div class="col-span-1 bg-white rounded-xl shadow p-5 text-center">
                    <div class="text-4xl font-black" :class="summary.score >= 0.70 ? 'text-green-600' : summary.score >= 0.40 ? 'text-yellow-600' : 'text-red-600'">
                        {{ scoreBar(summary.score) }}%
                    </div>
                    <div class="text-xs text-gray-500 mt-1">Score final</div>
                </div>
                <div class="bg-green-50 rounded-xl shadow p-5 text-center">
                    <div class="text-3xl font-black text-green-600">{{ summary.green }}</div>
                    <div class="text-xs text-green-600">Alcanzados</div>
                </div>
                <div class="bg-yellow-50 rounded-xl shadow p-5 text-center">
                    <div class="text-3xl font-black text-yellow-600">{{ summary.yellow }}</div>
                    <div class="text-xs text-yellow-600">Parciales</div>
                </div>
                <div class="bg-red-50 rounded-xl shadow p-5 text-center">
                    <div class="text-3xl font-black text-red-600">{{ summary.red }}</div>
                    <div class="text-xs text-red-600">No alcanzados</div>
                </div>
            </div>

            <!-- Reporte IA -->
            <div v-if="report" class="bg-gray-900 text-white rounded-2xl p-6 mb-6">
                <div class="flex items-center gap-2 mb-4">
                    <div class="w-8 h-8 bg-purple-600 rounded-full flex items-center justify-center text-white font-bold">C</div>
                    <span class="font-semibold">Análisis de Claude — Retrospectiva Q{{ cycle.quarter }}</span>
                </div>
                <div class="text-gray-300 text-sm leading-relaxed whitespace-pre-line">{{ report }}</div>
            </div>
            <div v-else class="bg-gray-50 rounded-2xl p-8 text-center text-gray-500 mb-6">
                <p class="text-lg mb-2">Sin análisis trimestral aún</p>
                <p class="text-sm">Haz clic en "Generar con IA" para que Claude analice el trimestre</p>
            </div>

            <!-- Tabla de objetivos -->
            <div class="bg-white rounded-2xl shadow overflow-hidden">
                <div class="p-4 bg-gray-50 border-b">
                    <h2 class="font-semibold text-gray-700">Resultados por objetivo</h2>
                </div>
                <div class="divide-y divide-gray-100">
                    <div v-for="obj in tree" :key="obj.id" class="p-4">
                        <div class="flex justify-between items-center mb-2">
                            <h3 class="font-medium text-sm text-gray-800">{{ obj.title }}</h3>
                            <span class="text-lg font-black" :class="obj.score >= 0.70 ? 'text-green-600' : obj.score >= 0.40 ? 'text-yellow-600' : 'text-red-600'">
                                {{ scoreBar(obj.score) }}%
                            </span>
                        </div>
                        <div class="space-y-1">
                            <div v-for="kr in obj.key_results" :key="kr.id"
                                 class="flex items-center gap-2 text-xs text-gray-600">
                                <div class="w-1.5 h-1.5 rounded-full shrink-0"
                                     :class="kr.traffic_light === 'green' ? 'bg-green-500' : kr.traffic_light === 'yellow' ? 'bg-yellow-500' : 'bg-red-500'">
                                </div>
                                <span class="flex-1 truncate">{{ kr.title }}</span>
                                <span>{{ kr.current }}/{{ kr.target }} {{ kr.unit }}</span>
                                <span class="font-bold">{{ scoreBar(kr.score) }}%</span>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </AppLayout>
</template>
VUE

# ── 7. COMPILAR Y CACHEAR ────────────────────────────────────────
echo ">>> Compilando assets Vue..."
npm run build

php artisan config:clear
php artisan route:clear
php artisan config:cache
php artisan route:cache
php artisan view:cache

echo ""
echo "========================================="
echo "  Sprint 08 completado exitosamente"
echo ""
echo "  Módulos creados:"
echo "  ✅ ChampionController (dashboard,"
echo "     CFR, agenda IA)"
echo "  ✅ RetrospectiveController"
echo "  ✅ 3 Notificaciones email"
echo "  ✅ Schedule: recordatorio semanal"
echo "  ✅ 3 vistas Vue: Dashboard, CFR,"
echo "     Retrospective"
echo ""
echo "  Rutas disponibles:"
echo "  /projects/{id}/cycles/{c}/champion"
echo "  /projects/{id}/cycles/{c}/champion/cfr"
echo "  /projects/{id}/cycles/{c}/retrospective"
echo "========================================="
