#!/bin/bash
# ================================================================
# OKRFEDEF — Sprint 11: Playbook OKR digital y onboarding
# Guías metodología, plantillas, tooltips, primer acceso
# Ejecutar desde: /home/evolucionamos/public_html/estrategia
# Comando: bash sprint_11_playbook.sh
# ================================================================
set -e
echo "========================================="
echo "  OKRFEDEF — Sprint 11: Playbook"
echo "========================================="

php artisan make:controller PlaybookController
php artisan make:seeder PlaybookSeeder

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

# ── 1. MIGRACIÓN PLAYBOOK ────────────────────────────────────────
cat > database/migrations/2026_03_25_100000_create_playbook_table.php << 'MIGRATION'
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

return new class extends Migration {
    public function up(): void {
        Schema::create('playbook_sections', function (Blueprint $table) {
            $table->id();
            $table->string('key')->unique();
            $table->string('title');
            $table->string('icon')->default('📖');
            $table->longText('content');
            $table->integer('order')->default(0);
            $table->json('roles_visible')->nullable();
            $table->timestamps();
        });
    }
    public function down(): void { Schema::dropIfExists('playbook_sections'); }
};
MIGRATION

php artisan migrate --force

# ── 2. MODELO ────────────────────────────────────────────────────
cat > app/Models/PlaybookSection.php << 'MODEL'
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;

class PlaybookSection extends Model {
    protected $table = 'playbook_sections';
    protected $fillable = ['key','title','icon','content','order','roles_visible'];
    protected $casts = ['roles_visible' => 'array'];
}
MODEL

# ── 3. PLAYBOOK SEEDER ───────────────────────────────────────────
cat > database/seeders/PlaybookSeeder.php << 'PHP'
<?php
namespace Database\Seeders;

use App\Models\PlaybookSection;
use Illuminate\Database\Seeder;

class PlaybookSeeder extends Seeder
{
    public function run(): void
    {
        $sections = [
            [
                'key'   => 'que_es_okr',
                'title' => '¿Qué son los OKRs?',
                'icon'  => '🎯',
                'order' => 1,
                'roles_visible' => ['consultor','sponsor','champion','owner','junta'],
                'content' => <<<CONTENT
## ¿Qué son los OKRs?

OKR significa **Objectives and Key Results** (Objetivos y Resultados Clave). Es una metodología de gestión de estrategia creada en Intel por Andy Grove y popularizada por Google. John Doerr la describe en su libro *Measure What Matters* (2018).

### Los 5 Superpoderes (FACTS)

| Superpoder | Qué significa |
|---|---|
| **F**ocus (Enfoque) | 3-5 objetivos que realmente importan, no 20 |
| **A**lignment (Alineación) | Todos conectados hacia los mismos resultados |
| **C**ommitment (Compromiso) | Responsables claros con rendición de cuentas |
| **T**racking (Seguimiento) | Medición continua con corrección temprana |
| **S**tretching (Ambición) | Metas retadoras que impulsan crecimiento |

### La diferencia con el BSC

El Balanced Scorecard planifica hacia adelante con métricas de control. Los OKRs son **hipótesis que se validan**: propones que si haces X, lograrás Y, y cada trimestre aprendes si tenías razón.

### Regla de oro

Un buen OKR tiene **60-70% de probabilidad de lograrse**. Si siempre llegas al 100%, tus metas no son lo suficientemente retadoras.
CONTENT,
            ],
            [
                'key'   => 'scoring',
                'title' => 'Escala de scoring (0.0 a 1.0)',
                'icon'  => '📊',
                'order' => 2,
                'roles_visible' => ['consultor','champion','owner'],
                'content' => <<<CONTENT
## Escala de scoring Doerr

El score de cada Key Result se calcula así:

```
score = (valor_actual - baseline) / (meta - baseline)
```

El resultado siempre queda entre 0.0 y 1.0.

### Semáforo

| Score | Color | Significado |
|---|---|---|
| ≥ 0.70 | 🟢 Verde | Logrado — ¡pero 1.0 exacto puede indicar meta poco retadora! |
| 0.40 – 0.69 | 🟡 Amarillo | En progreso — requiere atención |
| < 0.40 | 🔴 Rojo | En riesgo — requiere acción inmediata |

### Ejemplo práctico FEDEF

**KR:** Aumentar la colocación de crédito del 49.3% al 60% de la cartera potencial

- Baseline: 49.3%
- Meta: 60%
- Valor actual al check-in: 53%
- **Score:** (53 - 49.3) / (60 - 49.3) = 3.7 / 10.7 = **0.35** 🔴

Este KR está en rojo y requiere acción inmediata.

### El score del Objetivo

El score del Objetivo es el promedio de todos sus KRs:

```
score_objetivo = promedio(score_KR1, score_KR2, ..., score_KRn)
```
CONTENT,
            ],
            [
                'key'   => 'buenas_practicas_kr',
                'title' => 'Cómo escribir buenos Key Results',
                'icon'  => '✍️',
                'order' => 3,
                'roles_visible' => ['consultor','champion','owner'],
                'content' => <<<CONTENT
## Cómo escribir buenos Key Results

Un buen KR tiene 4 características: es **medible**, es un **resultado** (no una tarea), es **retador** y tiene un **dueño claro**.

### Prueba del Key Result

Antes de aprobar un KR, hazle estas 4 preguntas:

1. **¿Es medible?** ¿Puedes asignarle un número concreto?
2. **¿Es un resultado?** ¿Describe qué cambia en el mundo, no qué harás?
3. **¿Es retador?** ¿Tienes 60-70% de probabilidad de lograrlo?
4. **¿Tiene dueño?** ¿Hay una persona específica responsable?

### Ejemplos: malo vs bueno

| ❌ Malo (tarea) | ✅ Bueno (resultado) |
|---|---|
| Implementar sistema de captación digital | Lograr que el 60% de los asociados usen canales digitales |
| Hacer campañas de comunicación | Aumentar la satisfacción del asociado de 3.2 a 4.0 (encuesta NPS) |
| Revisar el proceso de crédito | Reducir el tiempo de aprobación de crédito de 5 a 2 días hábiles |
| Capacitar al equipo comercial | Aumentar la vinculación de nuevos asociados de 15 a 25 mensuales |

### Regla de la "semana pasada"

Si puedes decir "la semana pasada hice esto", es una tarea.
Si dices "la semana pasada LOGRAMOS esto", es un resultado.
CONTENT,
            ],
            [
                'key'   => 'cadencia_rituales',
                'title' => 'Cadencia y rituales OKR',
                'icon'  => '📅',
                'order' => 4,
                'roles_visible' => ['consultor','champion','owner','sponsor'],
                'content' => <<<CONTENT
## Cadencia y rituales OKR de FEDEF

### Ritual semanal — CFR (30 minutos)
**Quién facilita:** OKR Champion
**Quién participa:** Todo el equipo primario

**Estructura:**
1. Check-in de ánimo (1 palabra cada uno) — 5 min
2. KRs en rojo — 2 minutos por KR — 10 min
3. KRs en amarillo — 1 minuto cada uno — 7 min
4. Reconocimientos — celebrar avances — 5 min
5. Compromisos de la semana (máx 3, con dueño) — 3 min

**Regla de oro del CFR:** No es una reunión de reporte. Es una conversación sobre qué está pasando y qué necesita cambiar.

### Ritual mensual — Revisión gerencial (60 minutos)
**Quién facilita:** Gerente (Sponsor)
**Quién participa:** Directores + Champion

**Estructura:**
1. Dashboard con análisis de Claude — 15 min
2. Revisión por objetivo: logros y bloqueos — 30 min
3. Decisiones: ¿ajustamos metas? ¿cambiamos prioridades? — 10 min
4. Próximos pasos — 5 min

### Ritual trimestral — Retrospectiva (medio día)
**Quién facilita:** OKR Champion + Consultor (primero)
**Quién participa:** Todo el equipo + Junta

**Estructura:**
1. Análisis de Claude del ciclo — 30 min
2. ¿Qué funcionó? — 30 min
3. ¿Qué no funcionó y por qué? — 30 min
4. Hipótesis validadas vs refutadas — 30 min
5. Diseño del siguiente ciclo — 60 min

### Cuándo NO tener reuniones OKR
- Cuando el check-in ya está actualizado en la plataforma
- Cuando todos los KRs están en verde
- Para dar malas noticias (eso se hace directamente, no en el CFR)
CONTENT,
            ],
            [
                'key'   => 'rol_champion',
                'title' => 'El OKR Champion: guía completa',
                'icon'  => '🏆',
                'order' => 5,
                'roles_visible' => ['consultor','champion'],
                'content' => <<<CONTENT
## El OKR Champion

El Champion es el guardián de la metodología. No es el jefe de nadie — es el facilitador del sistema.

### Responsabilidades semanales

- [ ] Verificar que todos los owners ingresaron su check-in antes del CFR
- [ ] Generar la agenda CFR con la IA (botón en el dashboard)
- [ ] Facilitar la reunión CFR (30 minutos, máximo)
- [ ] Registrar los compromisos en la plataforma
- [ ] Alertar a la Gerencia si algún KR rojo no tiene plan de acción

### Responsabilidades mensuales

- [ ] Preparar el dashboard para la revisión gerencial
- [ ] Generar el análisis mensual con IA
- [ ] Revisar si hay KRs que necesitan ajuste de meta (con justificación)
- [ ] Enviar el resumen semanal a todos los participantes

### Responsabilidades trimestrales

- [ ] Facilitar la retrospectiva trimestral
- [ ] Asegurar que Claude genera el análisis del ciclo
- [ ] Documentar las hipótesis validadas y refutadas
- [ ] Liderar el diseño del siguiente ciclo

### Lo que NO debe hacer el Champion

- ❌ Hacer el check-in por otro — el owner siempre ingresa el suyo
- ❌ Cambiar metas sin consenso del equipo
- ❌ Cancelar el CFR porque "no hay nada nuevo" — siempre hay algo
- ❌ Convertir el CFR en una reunión de estado de tareas

### Señales de que el sistema está funcionando

- Los owners ingresan su check-in sin que el Champion tenga que recordarles
- Los KRs rojos tienen planes de acción documentados
- El equipo debate en el CFR, no solo reporta
- La Gerencia toma decisiones basadas en los scores, no en intuición
CONTENT,
            ],
            [
                'key'   => 'preguntas_frecuentes',
                'title' => 'Preguntas frecuentes',
                'icon'  => '❓',
                'order' => 6,
                'roles_visible' => ['consultor','sponsor','champion','owner','junta'],
                'content' => <<<CONTENT
## Preguntas frecuentes

**¿Qué hago si no voy a cumplir mi KR?**
Ingresa el check-in con el valor real y un nivel de confianza "bajo". Escribe una nota explicando qué está pasando. El Champion lo verá y lo pondrá en la agenda del próximo CFR.

**¿Se puede cambiar la meta a mitad del trimestre?**
Solo en casos excepcionales y con justificación documentada. Una meta que siempre se mueve no es una meta — es una estimación. El cambio debe pasar por el Champion y la Gerencia.

**¿Qué significa un score de 1.0?**
Que lograste exactamente la meta. Pero en la metodología Doerr, un 1.0 constante indica que tus metas no son suficientemente retadoras. El rango ideal de logro es 0.7-0.9.

**¿Cuántos KRs puede tener un Objetivo?**
Entre 2 y 5. Con más de 5 pierdes foco. Con menos de 2, probablemente no estás midiendo todo lo que importa.

**¿Qué pasa si mi KR depende de otro departamento?**
Documentalo en la sección de "dependencias" de la iniciativa. En el CFR, el Champion facilita el alineamiento entre los owners.

**¿La Junta Directiva puede cambiar los OKRs?**
La JD aprueba los OKRs institucionales. Puede sugerir ajustes, pero los cambios operativos los lidera el equipo directivo con el Champion.

**¿Cada cuánto tiempo se revisan los OKRs con la IA?**
- Check-in semanal: Claude no participa automáticamente, solo cuando el Champion genera la agenda CFR
- Mensual: Claude genera el análisis automáticamente
- Trimestral: Claude genera la retrospectiva completa
- En cualquier momento: puedes preguntarle al chat de Claude
CONTENT,
            ],
        ];

        foreach ($sections as $section) {
            PlaybookSection::updateOrCreate(
                ['key' => $section['key']],
                $section
            );
        }

        echo count($sections) . " secciones del Playbook creadas.\n";
    }
}
PHP

# ── 4. PLAYBOOK CONTROLLER ───────────────────────────────────────
cat > app/Http/Controllers/PlaybookController.php << 'PHP'
<?php
namespace App\Http\Controllers;

use App\Models\AiMessage;
use App\Models\PlaybookSection;
use App\Models\Project;
use App\Services\ClaudeService;
use Illuminate\Http\Request;
use Inertia\Inertia;

class PlaybookController extends Controller
{
    public function __construct(private ClaudeService $claude) {}

    public function index(Project $project)
    {
        $userRole = auth()->user()->roles->first()?->name ?? 'owner';

        $sections = PlaybookSection::orderBy('order')
            ->get()
            ->filter(fn($s) => empty($s->roles_visible) || in_array($userRole, $s->roles_visible ?? []))
            ->values();

        return Inertia::render('Playbook/Index', [
            'project'  => $project->load('organization'),
            'sections' => $sections,
            'userRole' => $userRole,
        ]);
    }

    public function show(Project $project, PlaybookSection $section)
    {
        return Inertia::render('Playbook/Section', [
            'project' => $project->load('organization'),
            'section' => $section,
        ]);
    }

    /**
     * Chat con Claude sobre la metodología OKR
     * Claude responde con ejemplos específicos de FEDEF
     */
    public function askMethodology(Request $request, Project $project)
    {
        $request->validate(['question' => 'required|string|max:500']);

        $systemPrompt = "Eres el experto en metodología OKR de OKRFEDEF. " .
            "Responde preguntas sobre la metodología OKR (Doerr), Estrategia Emergente (Salazar) " .
            "y cómo aplicarlas en {$project->organization->name}. " .
            "Usa ejemplos concretos del contexto de un fondo de empleados cuando sea posible. " .
            "Sé directo y práctico. Máximo 200 palabras.";

        $response = $this->claude->ask($request->question, $systemPrompt, 500);

        AiMessage::create([
            'project_id' => $project->id,
            'user_id'    => auth()->id(),
            'module'     => 'chat',
            'context'    => ['type' => 'playbook_question'],
            'prompt'     => $request->question,
            'response'   => $response ?? 'No pude responder. Intenta de nuevo.',
            'model'      => config('services.anthropic.model'),
            'trigger'    => 'consultive',
        ]);

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

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

// ── Playbook Routes ───────────────────────────────────────────────
use App\Http\Controllers\PlaybookController;

Route::middleware(['auth', 'verified'])->prefix('projects/{project}/playbook')->group(function () {
    Route::get('/',                    [PlaybookController::class, 'index'])->name('playbook.index');
    Route::get('/{section}',           [PlaybookController::class, 'show'])->name('playbook.section');
    Route::post('/ask',                [PlaybookController::class, 'askMethodology'])->name('playbook.ask');
});
PHP

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

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

const props = defineProps({
    project: Object,
    sections: Array,
    userRole: String,
})

const question = ref('')
const answer = ref(null)
const asking = ref(false)

const askClaude = async () => {
    if (!question.value.trim() || asking.value) return
    asking.value = true
    answer.value = null
    try {
        const res = await axios.post(route('playbook.ask', props.project.id), { question: question.value })
        answer.value = res.data.response
    } finally { asking.value = false }
}

const roleLabels = {
    consultor: 'Consultor',
    sponsor: 'Sponsor / Gerencia',
    champion: 'OKR Champion',
    owner: 'Owner / Director',
    junta: 'Junta Directiva',
}
</script>

<template>
    <AppLayout :title="`Playbook OKR — ${project.name}`">
        <div class="max-w-4xl mx-auto px-4 py-8">

            <div class="mb-8">
                <h1 class="text-2xl font-bold text-gray-900">Playbook OKR</h1>
                <p class="text-gray-500 mt-1">{{ project.organization?.name }} · Tu rol: <strong>{{ roleLabels[userRole] }}</strong></p>
            </div>

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

                <!-- Secciones del playbook -->
                <div class="col-span-2 space-y-3">
                    <a v-for="section in sections" :key="section.id"
                       :href="route('playbook.section', [project.id, section.id])"
                       class="flex items-start gap-4 bg-white rounded-2xl shadow hover:shadow-md transition-all p-4 border border-transparent hover:border-green-200 group">
                        <div class="text-3xl">{{ section.icon }}</div>
                        <div class="flex-1">
                            <h2 class="font-semibold text-gray-800 group-hover:text-green-700 transition-colors">{{ section.title }}</h2>
                            <p class="text-xs text-gray-400 mt-1 line-clamp-2">
                                {{ section.content.substring(0, 100).replace(/[#*|`]/g, '') }}...
                            </p>
                        </div>
                        <span class="text-gray-300 group-hover:text-green-500 text-lg">→</span>
                    </a>
                </div>

                <!-- Chat con Claude sobre metodología -->
                <div>
                    <div class="bg-gray-900 rounded-2xl p-4 sticky top-6">
                        <div class="flex items-center gap-2 mb-4">
                            <div class="w-6 h-6 bg-purple-600 rounded-full flex items-center justify-center text-white text-xs font-bold">C</div>
                            <span class="text-white text-sm font-medium">Pregúntale a Claude</span>
                        </div>

                        <div v-if="answer" class="bg-gray-800 rounded-xl p-3 mb-3">
                            <p class="text-gray-200 text-xs leading-relaxed whitespace-pre-line">{{ answer }}</p>
                        </div>

                        <div class="space-y-2">
                            <textarea v-model="question" rows="3"
                                      placeholder="¿Cómo escribo un buen KR para el área de crédito?"
                                      class="w-full bg-gray-800 text-white text-xs rounded-xl p-3 resize-none outline-none focus:ring-1 focus:ring-purple-500 placeholder-gray-500">
                            </textarea>
                            <button @click="askClaude" :disabled="asking || !question.trim()"
                                    class="w-full bg-purple-600 hover:bg-purple-700 disabled:bg-gray-700 text-white py-2 rounded-xl text-sm font-medium transition-colors">
                                {{ asking ? 'Consultando...' : 'Preguntar' }}
                            </button>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </AppLayout>
</template>
VUE

cat > resources/js/Pages/Playbook/Section.vue << 'VUE'
<script setup>
import { Link } from '@inertiajs/vue3'
import AppLayout from '@/Layouts/AppLayout.vue'

const props = defineProps({
    project: Object,
    section: Object,
})

// Renderizado simple de markdown básico
const renderMarkdown = (text) => {
    return text
        .replace(/^### (.+)$/gm, '<h3 class="text-base font-semibold text-gray-800 mt-4 mb-2">$1</h3>')
        .replace(/^## (.+)$/gm, '<h2 class="text-lg font-bold text-gray-900 mt-6 mb-3 border-b border-gray-200 pb-2">$1</h2>')
        .replace(/\*\*(.+?)\*\*/g, '<strong>$1</strong>')
        .replace(/`(.+?)`/g, '<code class="bg-gray-100 px-1 py-0.5 rounded text-sm font-mono text-blue-700">$1</code>')
        .replace(/^- \[ \] (.+)$/gm, '<div class="flex gap-2 items-start my-1"><div class="w-4 h-4 border-2 border-gray-300 rounded mt-0.5 shrink-0"></div><span>$1</span></div>')
        .replace(/^- \[x\] (.+)$/gm, '<div class="flex gap-2 items-start my-1"><div class="w-4 h-4 bg-green-500 rounded mt-0.5 shrink-0 flex items-center justify-center text-white text-xs">✓</div><span class="line-through text-gray-400">$1</span></div>')
        .replace(/^- ❌ (.+)$/gm, '<div class="flex gap-2 my-1"><span class="text-red-500">❌</span><span>$1</span></div>')
        .replace(/^- ✅ (.+)$/gm, '<div class="flex gap-2 my-1"><span class="text-green-500">✅</span><span>$1</span></div>')
        .replace(/^- (.+)$/gm, '<li class="ml-4 my-1 text-gray-700">$1</li>')
        .replace(/\n/g, '<br>')
}
</script>

<template>
    <AppLayout :title="`${section.title} — Playbook`">
        <div class="max-w-3xl mx-auto px-4 py-8">

            <div class="mb-6 flex items-center gap-3">
                <a :href="route('playbook.index', project.id)" class="text-gray-400 hover:text-gray-600 text-sm">← Playbook</a>
            </div>

            <div class="bg-white rounded-2xl shadow p-8">
                <div class="flex items-center gap-3 mb-6">
                    <span class="text-4xl">{{ section.icon }}</span>
                    <h1 class="text-2xl font-bold text-gray-900">{{ section.title }}</h1>
                </div>

                <div class="prose max-w-none text-gray-700 leading-relaxed"
                     v-html="renderMarkdown(section.content)">
                </div>
            </div>
        </div>
    </AppLayout>
</template>
VUE

# ── 7. EJECUTAR SEEDER ───────────────────────────────────────────
php artisan db:seed --class=PlaybookSeeder

# ── 8. 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 11 completado exitosamente"
echo ""
echo "  ✅ PlaybookController"
echo "  ✅ PlaybookSeeder (6 secciones)"
echo "     - ¿Qué son los OKRs?"
echo "     - Escala de scoring Doerr"
echo "     - Cómo escribir buenos KRs"
echo "     - Cadencia y rituales"
echo "     - Guía del Champion"
echo "     - Preguntas frecuentes"
echo "  ✅ Chat con Claude sobre metodología"
echo "  ✅ 2 vistas: Index, Section"
echo ""
echo "  Ruta: /projects/{id}/playbook"
echo "========================================="
