<?php
// /exercises.php

// --- 1. GESTIÓN DE SESIÓN Y DEPENDENCIAS ---
session_start();
if (!isset($_SESSION['user_id'])) { header('Location: index.php'); exit; }

require_once 'db.php';
$user_rol = $_SESSION['user_rol'];
$user_id = $_SESSION['user_id'];
if (!defined('RECORDS_PER_PAGE')) {
    define('RECORDS_PER_PAGE', $_SESSION['records_per_page'] ?? 8);
}

// --- OBTENER PREFERENCIA DE FILTRO Y VISTA DEL USUARIO ---
$filtro_defecto = 0;
$user_view_prefs_json = '{}'; // Por defecto, un JSON vacío
if (in_array($user_rol, ['superadmin', 'fisio'])) {
    // Leemos ambas columnas de preferencias
    $stmt_prefs = $db->prepare("SELECT filtro_personal_defecto, vista_defecto FROM cuentas WHERE id = ?");
    $stmt_prefs->execute([$user_id]);
    if ($user_prefs = $stmt_prefs->fetch(PDO::FETCH_ASSOC)) {
        $filtro_defecto = $user_prefs['filtro_personal_defecto'];
        // Aseguramos que pasamos un JSON válido a JS, incluso si es null en la BD
        $user_view_prefs_json = $user_prefs['vista_defecto'] ?? '{}';
    }
}

// --- 2. GESTOR DE PETICIONS AJAX ---
if (isset($_REQUEST['ajax'])) {
    header('Content-Type: application/json');
    $action = $_REQUEST['action'] ?? 'read';

    try {
        // **INICIO MODIFICACIÓN**: Asumimos que existe esta tabla:
        // CREATE TABLE IF NOT EXISTS ejercicio_fisios_asignados (
        //     id INTEGER PRIMARY KEY AUTOINCREMENT,
        //     ejercicio_id INTEGER NOT NULL,
        //     fisio_id INTEGER NOT NULL,
        //     FOREIGN KEY (ejercicio_id) REFERENCES ejercicios(id) ON DELETE CASCADE,
        //     FOREIGN KEY (fisio_id) REFERENCES cuentas(id) ON DELETE CASCADE,
        //     UNIQUE(ejercicio_id, fisio_id)
        // );

        switch ($action) {

          case 'read':
                          $page = (int)($_GET['page'] ?? 1);
                          $search = $_GET['search'] ?? '';
                          // ★★★ AÑADIR ESTA LÍNEA ★★★
                          $categoryId = $_GET['categoryId'] ?? '';
                          // ★★★ FIN ★★★

                          $valid_sorts = ['creation_date', 'title', 'category_name', 'creator_surname'];
                          $sort = in_array($_GET['sort'] ?? '', $valid_sorts) ? $_GET['sort'] : 'creation_date';
                          $order = ($_GET['order'] ?? 'DESC') === 'ASC' ? 'ASC' : 'DESC';
                          $filterMine = ($_GET['filterMine'] ?? 'false') === 'true';

                          $params = [':search' => '%' . $search . '%'];
                          $joins = "
                              JOIN cuentas c ON e.id_creator = c.id
                              LEFT JOIN videos v ON e.id_video = v.id
                              LEFT JOIN images i ON e.id_image = i.id
                              LEFT JOIN categorias cat ON e.id_categoria = cat.id
                          ";
                          $whereClause = "WHERE (e.title LIKE :search OR e.notes LIKE :search)";

                          // ★★★ AÑADIR ESTE BLOQUE ★★★
                          if (!empty($categoryId)) {
                              $whereClause .= " AND e.id_categoria = :category_id";
                              $params[':category_id'] = $categoryId;
                          }
                          // ★★★ FIN ★★★

                          // **MODIFICADO**: filterMine ahora incluye creador O colaborador
                          if ($filterMine && in_array($user_rol, ['superadmin', 'fisio'])) {
                              $whereClause .= " AND (
                                  e.id_creator = :user_id
                                  OR EXISTS (
                                      SELECT 1 FROM ejercicio_fisios_asignados tfa
                                      WHERE tfa.ejercicio_id = e.id AND tfa.fisio_id = :user_id
                                  )
                              )";
                              $params[':user_id'] = $user_id;
                          }

                          if (in_array($user_rol, ['superadmin', 'fisio'])) {
                              $whereClause .= " AND NOT EXISTS (SELECT 1 FROM archivado_personal ap WHERE ap.item_id = e.id AND ap.item_type = 'ejercicio' AND ap.fisio_id = :current_fisio_id)";
                              $params[':current_fisio_id'] = $user_id;
                          }

                          $totalQuery = "SELECT COUNT(e.id) FROM ejercicios e $whereClause";
                          $totalStmt = $db->prepare($totalQuery);
                          $totalStmt->execute($params);
                          $totalRecords = $totalStmt->fetchColumn();
                          $totalPages = ceil($totalRecords / RECORDS_PER_PAGE);

                          $offset = ($page - 1) * RECORDS_PER_PAGE;

                          $orderByColumn = match ($sort) {
                              'title' => 'LOWER(e.title)',
                              'category_name' => 'LOWER(cat.name)',
                              'creator_surname' => 'LOWER(c.apellido)',
                              'creation_date' => 'e.creation_date',
                              default => 'e.creation_date',
                          };

                          // --- ★★★ INICIO CORRECCIÓN MYSQL ★★★ ---
                          // Se usa CONCAT() en lugar de ||
                          // Se usa SEPARATOR ', ' dentro de GROUP_CONCAT
                          $dataQuery = "SELECT e.*, v.filename as video_filename, i.filename as image_filename,
                                               c.nombre as creator_name, c.apellido as creator_surname, cat.name as category_name,
                                               (SELECT GROUP_CONCAT(tfa.fisio_id)
                                                FROM ejercicio_fisios_asignados tfa
                                                WHERE tfa.ejercicio_id = e.id
                                               ) as collaborator_ids,
                                               (SELECT GROUP_CONCAT(CONCAT(colab.nombre, ' ', colab.apellido) SEPARATOR ', ')
                                                FROM ejercicio_fisios_asignados tfa
                                                JOIN cuentas colab ON tfa.fisio_id = colab.id
                                                WHERE tfa.ejercicio_id = e.id AND tfa.fisio_id != e.id_creator
                                               ) as collaborators
                                        FROM ejercicios e $joins $whereClause
                                        ORDER BY $orderByColumn $order
                                        LIMIT :limit OFFSET :offset";
                          // --- ★★★ FIN CORRECCIÓN MYSQL ★★★ ---

                          $dataStmt = $db->prepare($dataQuery);
                          foreach ($params as $key => &$val) $dataStmt->bindParam($key, $val);
                          $dataStmt->bindValue(':limit', RECORDS_PER_PAGE, PDO::PARAM_INT);
                          $dataStmt->bindValue(':offset', $offset, PDO::PARAM_INT);
                          $dataStmt->execute();
                          $exercicis = $dataStmt->fetchAll();

                          $exerciseIds = array_column($exercicis, 'id');
                          if(count($exerciseIds) > 0) {
                              $tagsQuery = $db->prepare("SELECT et.ejercicio_id, t.name FROM ejercicio_tags et JOIN tags t ON et.tag_id = t.id WHERE et.ejercicio_id IN (" . implode(',', array_fill(0, count($exerciseIds), '?')) . ")");
                              $tagsQuery->execute($exerciseIds);
                              $tagsByExercise = $tagsQuery->fetchAll(PDO::FETCH_GROUP);
                              foreach($exercicis as &$exercise) {
                                  $exercise['tags'] = isset($tagsByExercise[$exercise['id']]) ? $tagsByExercise[$exercise['id']] : [];
                                  // **NUEVO**: Asegurar strings vacíos
                                  if ($exercise['collaborator_ids'] === null) $exercise['collaborator_ids'] = '';
                                  if ($exercise['collaborators'] === null) $exercise['collaborators'] = '';
                              }
                          }

                          echo json_encode(['status' => 'success', 'data' => $exercicis, 'pagination' => ['currentPage' => $page, 'totalPages' => $totalPages, 'currentSort' => $sort, 'currentOrder' => $order]]);
                          break;

            case 'get_rich_exercise_library':
                $search = $_GET['search'] ?? '';
                $category = $_GET['category'] ?? null;
                $tags = isset($_GET['tags']) && is_array($_GET['tags']) ? $_GET['tags'] : [];
                $filterMine = ($_GET['filterMine'] ?? 'false') === 'true';

                $params = [':search' => '%' . $search . '%'];
                $whereClause = "WHERE LOWER(e.title) LIKE LOWER(:search)";
                $joins = "
                    LEFT JOIN videos v ON e.id_video = v.id
                    LEFT JOIN images i ON e.id_image = i.id
                ";

                // **MODIFICADO**: filterMine ahora incluye creador O colaborador
                if ($filterMine && in_array($user_rol, ['superadmin', 'fisio'])) {
                    $whereClause .= " AND (
                        e.id_creator = :user_id
                        OR EXISTS (
                            SELECT 1 FROM ejercicio_fisios_asignados tfa
                            WHERE tfa.ejercicio_id = e.id AND tfa.fisio_id = :user_id
                        )
                    )";
                    $params[':user_id'] = $user_id;
                }

                if (!empty($category)) {
                    $whereClause .= " AND e.id_categoria = :category";
                    $params[':category'] = $category;
                }

                if (!empty($tags)) {
                    $tagPlaceholders = implode(',', array_fill(0, count($tags), '?'));
                    $whereClause .= " AND e.id IN (SELECT ejercicio_id FROM ejercicio_tags WHERE tag_id IN ($tagPlaceholders) GROUP BY ejercicio_id HAVING COUNT(DISTINCT tag_id) = ?)";
                    foreach($tags as $tag) {
                        $params[] = $tag;
                    }
                    $params[] = count($tags);
                }

                if (in_array($user_rol, ['superadmin', 'fisio'])) {
                    $whereClause .= " AND NOT EXISTS (SELECT 1 FROM archivado_personal ap WHERE ap.item_id = e.id AND ap.item_type = 'ejercicio' AND ap.fisio_id = :current_fisio_id)";
                    $params[':current_fisio_id'] = $user_id;
                }

                $query = "SELECT e.*, v.filename as video_filename, i.filename as image_filename FROM ejercicios e $joins $whereClause ORDER BY LOWER(e.title) ASC";

                if(!empty($tags)) {
                    $query = str_replace('(?)', "(".implode(',', array_map('intval', $tags)).")", $query);
                    $stmt = $db->prepare($query);
                    $finalParams = [];
                    foreach($params as $key => $value){
                        if(is_numeric($key) && in_array($value, $tags)) continue;
                        if(is_numeric($key) && $value == count($tags)) continue;
                        $finalParams[$key] = $value;
                    }
                     $stmt->execute($finalParams);
                } else {
                     $stmt = $db->prepare($query);
                     $stmt->execute($params);
                }

                $exercises = $stmt->fetchAll();
                echo json_encode(['status' => 'success', 'exercises' => $exercises]);
                break;


            case 'get_exercise':
                $id = (int)$_GET['id'];
                $stmt = $db->prepare("
                    SELECT e.*, v.filename as video_filename, i.filename as image_filename, cat.name as category_name, c.nombre as creator_name, c.apellido as creator_surname
                    FROM ejercicios e
                    LEFT JOIN videos v ON e.id_video = v.id
                    LEFT JOIN images i ON e.id_image = i.id
                    LEFT JOIN categorias cat ON e.id_categoria = cat.id
                    LEFT JOIN cuentas c ON e.id_creator = c.id
                    WHERE e.id = ?
                ");
                $stmt->execute([$id]);
                $exercise = $stmt->fetch();
                if (!$exercise) { throw new Exception("Exercici no trobat."); }

                $tagsStmt = $db->prepare("SELECT t.id, t.name FROM ejercicio_tags et JOIN tags t ON et.tag_id = t.id WHERE et.ejercicio_id = ?");
                $tagsStmt->execute([$id]);
                $exercise['tags'] = $tagsStmt->fetchAll(PDO::FETCH_ASSOC);

                $tagsStmt_ids = $db->prepare("SELECT tag_id FROM ejercicio_tags WHERE ejercicio_id = ?");
                $tagsStmt_ids->execute([$id]);
                $exercise['tags_ids'] = $tagsStmt_ids->fetchAll(PDO::FETCH_COLUMN);

                // **NUEVO**: Obtener fisios colaboradores
                $stmtFisios = $db->prepare("SELECT fisio_id FROM ejercicio_fisios_asignados WHERE ejercicio_id = ?");
                $stmtFisios->execute([$id]);
                $exercise['assigned_fisios'] = $stmtFisios->fetchAll(PDO::FETCH_COLUMN);

                echo json_encode(['status' => 'success', 'data' => $exercise]);
                break;

            case 'create':
            case 'update':
                $db->beginTransaction();
                $id_video = !empty($_POST['id_video']) ? (int)$_POST['id_video'] : null;
                $id_image = !empty($_POST['id_image']) ? (int)$_POST['id_image'] : null;
                $id_categoria = !empty($_POST['id_categoria']) ? (int)$_POST['id_categoria'] : null;
                $title = trim($_POST['title']);
                $assignedFisios = $_POST['assigned_fisios'] ?? []; // **NUEVO**

                if (empty($title) || empty($_POST['series']) || empty($_POST['repetitions']) || empty($_POST['rest_time'])) { throw new Exception("Tots els camps amb * són obligatoris."); }
                if (empty($id_categoria) || empty($_POST['tags'])) { throw new Exception("Cal seleccionar almenys una categoria i una etiqueta."); }

                $tags = explode(',', $_POST['tags']);

                if ($action === 'create') {
                    // La tabla 'ejercicios' debe tener 'creation_date' con DEFAULT CURRENT_TIMESTAMP
                    $stmt = $db->prepare("INSERT INTO ejercicios (id_video, id_image, id_creator, id_categoria, title, series, repetitions, rest_time, notes) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)");
                    $stmt->execute([$id_video, $id_image, $user_id, $id_categoria, $title, $_POST['series'], $_POST['repetitions'], $_POST['rest_time'], $_POST['notes']]);
                    $exerciseId = $db->lastInsertId();

                    // **NUEVO**: Insertar colaboradores (incluyendo creador)
                    if (!in_array($user_id, $assignedFisios)) { $assignedFisios[] = $user_id; }
                    $fisioStmt = $db->prepare("INSERT INTO ejercicio_fisios_asignados (ejercicio_id, fisio_id) VALUES (?, ?)");
                    foreach(array_unique($assignedFisios) as $fisioId) {
                        if(!empty($fisioId)) $fisioStmt->execute([$exerciseId, $fisioId]);
                    }

                } else { // 'update'
                    $exerciseId = (int)$_POST['id'];

                    // **NUEVO**: Comprobar permisos (Creador, Colaborador o Superadmin)
                    if ($user_rol === 'fisio') {
                        $permStmt = $db->prepare("
                            SELECT 1 FROM ejercicios e
                            LEFT JOIN ejercicio_fisios_asignados tfa ON e.id = tfa.ejercicio_id
                            WHERE e.id = ? AND (e.id_creator = ? OR tfa.fisio_id = ?)
                            LIMIT 1
                        ");
                        $permStmt->execute([$exerciseId, $user_id, $user_id]);
                        if (!$permStmt->fetch()) {
                            throw new Exception("No tens permís per a editar aquest exercici.");
                        }
                    }

                    // **MODIFICADO**: Eliminada la comprobación de 'id_creator' de la query
                    $query = "UPDATE ejercicios SET id_video=?, id_image=?, id_categoria=?, title=?, series=?, repetitions=?, rest_time=?, notes=? WHERE id=?";
                    $params = [$id_video, $id_image, $id_categoria, $title, $_POST['series'], $_POST['repetitions'], $_POST['rest_time'], $_POST['notes'], $exerciseId];

                    $stmt = $db->prepare($query);
                    $stmt->execute($params);

                    // **NUEVO**: Actualizar colaboradores (Solo si es Creador o Superadmin)
                    $creatorStmt = $db->prepare("SELECT id_creator FROM ejercicios WHERE id = ?");
                    $creatorStmt->execute([$exerciseId]);
                    $creator_id = $creatorStmt->fetchColumn();

                    if ($user_rol === 'superadmin' || $user_id == $creator_id) {
                        $db->prepare("DELETE FROM ejercicio_fisios_asignados WHERE ejercicio_id = ?")->execute([$exerciseId]);
                        if ($creator_id && !in_array($creator_id, $assignedFisios)) {
                            $assignedFisios[] = $creator_id;
                        }
                        $fisioStmt = $db->prepare("INSERT INTO ejercicio_fisios_asignados (ejercicio_id, fisio_id) VALUES (?, ?)");
                        foreach(array_unique($assignedFisios) as $fisioId) {
                            if(!empty($fisioId)) $fisioStmt->execute([$exerciseId, $fisioId]);
                        }
                    }
                }

                $db->prepare("DELETE FROM ejercicio_tags WHERE ejercicio_id = ?")->execute([$exerciseId]);
                if (!empty($tags[0])) {
                    $tagStmt = $db->prepare("INSERT INTO ejercicio_tags (ejercicio_id, tag_id) VALUES (?, ?)");
                    foreach ($tags as $tagId) {
                        if (!empty($tagId)) $tagStmt->execute([$exerciseId, (int)$tagId]);
                    }
                }
                $db->commit();
                // --- MODIFICACIÓN 1 (FLASH) ---
                echo json_encode(['status' => 'success', 'message' => 'Exercici guardat correctament.', 'saved_exercise_id' => $exerciseId]);
                break;

            case 'clone_exercise':
                $originalExerciseId = (int)$_POST['original_exercise_id'];
                $newTitle = trim($_POST['title']);

                if (empty($newTitle)) {
                    throw new Exception("El títol no pot estar buit.");
                }

                $db->beginTransaction();

                // --- ★ TAREA 3 (Clonación Lógica) ---
                // 1. Pedimos la fecha de creación original
                $stmtOrig = $db->prepare("SELECT *, creation_date as original_creation_date FROM ejercicios WHERE id = ?");
                $stmtOrig->execute([$originalExerciseId]);
                $originalExercise = $stmtOrig->fetch(PDO::FETCH_ASSOC);

                if (!$originalExercise) {
                    throw new Exception("L'exercici original no s'ha trobat.");
                }

                // 2. Añadimos 'creation_date' al INSERT y usamos DATE_ADD
                $stmtNew = $db->prepare("
                    INSERT INTO ejercicios (id_video, id_image, id_creator, id_categoria, title, series, repetitions, rest_time, notes, creation_date)
                    VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, DATE_ADD(?, INTERVAL 1 SECOND))
                ");
                $stmtNew->execute([
                    $originalExercise['id_video'],
                    $originalExercise['id_image'],
                    $user_id, // New creator
                    $originalExercise['id_categoria'],
                    $newTitle, // New title
                    $originalExercise['series'],
                    $originalExercise['repetitions'],
                    $originalExercise['rest_time'],
                    $originalExercise['notes'],
                    $originalExercise['original_creation_date'] // <-- 3. Pasamos la fecha original
                ]);
                $newExerciseId = $db->lastInsertId();
                // --- ★ FIN TAREA 3 ---


                // Clonar Tags
                $stmtTags = $db->prepare("SELECT tag_id FROM ejercicio_tags WHERE ejercicio_id = ?");
                $stmtTags->execute([$originalExerciseId]);
                $tagIds = $stmtTags->fetchAll(PDO::FETCH_COLUMN);

                if (!empty($tagIds)) {
                    $stmtTagNew = $db->prepare("INSERT INTO ejercicio_tags (ejercicio_id, tag_id) VALUES (?, ?)");
                    foreach ($tagIds as $tagId) {
                        $stmtTagNew->execute([$newExerciseId, $tagId]);
                    }
                }

                // **NUEVO**: Clonar Colaboradores
                $stmtColab = $db->prepare("SELECT fisio_id FROM ejercicio_fisios_asignados WHERE ejercicio_id = ?");
                $stmtColab->execute([$originalExerciseId]);
                $colabIds = $stmtColab->fetchAll(PDO::FETCH_COLUMN);

                if (!in_array($user_id, $colabIds)) { // Añadir nuevo creador
                    $colabIds[] = $user_id;
                }
                $stmtColabNew = $db->prepare("INSERT INTO ejercicio_fisios_asignados (ejercicio_id, fisio_id) VALUES (?, ?)");
                foreach (array_unique($colabIds) as $fisioId) {
                    if(!empty($fisioId)) $stmtColabNew->execute([$newExerciseId, $fisioId]);
                }

                $db->commit();
                // --- MODIFICACIÓN 2 (FLASH) ---
                echo json_encode(['status' => 'success', 'message' => 'Exercici clonat correctament.', 'new_exercise_id' => $newExerciseId]);
                break;

                case 'personal_archive':
                                if (!in_array($user_rol, ['superadmin', 'fisio'])) { throw new Exception('Accés denegat.'); }
                                // --- CORRECCIÓN MYSQL ---
                                $stmt = $db->prepare("INSERT IGNORE INTO archivado_personal (fisio_id, item_id, item_type) VALUES (?, ?, 'ejercicio')");
                                // --- FIN CORRECCIÓN ---
                                $stmt->execute([$user_id, (int)$_POST['id']]);
                                echo json_encode(['status' => 'success', 'message' => 'Exercici arxivat correctament a la teua vista.']);
                                break;

                case 'delete':
                                $id = (int)$_POST['id'];

                                // ¡AQUÍ LA MODIFICACIÓN!
                                // Solo comprobamos el uso SI NO ERES superadmin.
                                if ($user_rol !== 'superadmin') {
                                    $usageStmt = $db->prepare("SELECT COUNT(t.id) FROM tratamiento_ejercicios te JOIN tratamientos t ON te.tratamiento_id = t.id WHERE te.ejercicio_id = ? AND (t.is_protocol = 1 OR t.status = 'En curs')");
                                    $usageStmt->execute([$id]);
                                    if ($usageStmt->fetchColumn() > 0) {
                                        throw new Exception("L'exercici està en ús en un tractament actiu o protocol i no pot ser eliminat.");
                                    }
                                }
                                // FIN DE LA MODIFICACIÓN

                                // El resto de tu lógica de permisos (comprobar si es creador) está bien
                                $query = "DELETE FROM ejercicios WHERE id = ?";
                                $params = [$id];
                                if ($user_rol === 'fisio') {
                                    $stmtCheck = $db->prepare("SELECT 1 FROM ejercicios WHERE id = ? AND id_creator = ?");
                                    $stmtCheck->execute([$id, $user_id]);
                                    if (!$stmtCheck->fetch()) {
                                        throw new Exception('No tens permís per a eliminar aquest exercici (només el creador o superadmin poden).');
                                    }
                                    $query .= " AND id_creator = ?";
                                    $params[] = $user_id;
                                }

                                $stmt = $db->prepare($query);
                                $stmt->execute($params);

                                if ($stmt->rowCount() > 0) {
                                    $db->prepare("DELETE FROM ejercicio_tags WHERE ejercicio_id = ?")->execute([$id]);
                                    $db->prepare("DELETE FROM ejercicio_fisios_asignados WHERE ejercicio_id = ?")->execute([$id]);
                                } else if ($user_rol === 'fisio') {
                                    throw new Exception('No s\'ha trobat l\'exercici o no tens permís.');
                                }

                                echo json_encode(['status' => 'success', 'message' => "L'exercici ha sigut eliminat permanentment."]);
                                break;

            case 'check_exercise_usage':
                $id = (int)$_GET['id'];
                $stmt = $db->prepare("SELECT 'Tractament Actiu/Protocol' as type, t.title as name FROM tratamiento_ejercicios te JOIN tratamientos t ON te.tratamiento_id = t.id WHERE te.ejercicio_id = :id AND (t.is_protocol = 1 OR t.status = 'En curs')");
                $stmt->execute([':id' => $id]);
                $usage = $stmt->fetchAll();
                echo json_encode(['is_usable_for_action' => (count($usage) === 0), 'usage' => $usage]);
                break;

            case 'get_form_dependencies':
                $catsStmt = $db->query("SELECT * FROM categorias ORDER BY parent_id, name");
                $tagsStmt = $db->query("SELECT * FROM tags ORDER BY parent_id, name");

                // **NUEVO**: Obtener fisios
                $fisiosStmt = $db->query("SELECT id, nombre, apellido FROM cuentas WHERE rol IN ('fisio', 'superadmin') AND is_archived = 0 ORDER BY apellido, nombre");

                $videosQuery = "
                    SELECT id, title, description, filename, id_uploader FROM videos v
                    WHERE NOT EXISTS (
                        SELECT 1 FROM archivado_personal ap
                        WHERE ap.item_id = v.id AND ap.item_type = 'video' AND ap.fisio_id = ?
                    )
                    ORDER BY title ASC
                ";
                $videosStmt = $db->prepare($videosQuery);
                $videosStmt->execute([$user_id]);

                $imagesQuery = "
                    SELECT id, title, description, filename, id_uploader FROM images i
                    WHERE i.filename NOT IN ('logo.jpg', 'logo2.jpg', 'img_defecte.jpg')
                    AND NOT EXISTS (
                        SELECT 1 FROM archivado_personal ap
                        WHERE ap.item_id = i.id AND ap.item_type = 'image' AND ap.fisio_id = ?
                    )
                    ORDER BY title ASC
                ";
                $imagesStmt = $db->prepare($imagesQuery);
                $imagesStmt->execute([$user_id]);

                echo json_encode([
                    'status' => 'success',
                    'categories' => $catsStmt->fetchAll(PDO::FETCH_ASSOC),
                    'tags' => $tagsStmt->fetchAll(PDO::FETCH_ASSOC),
                    'videos' => $videosStmt->fetchAll(PDO::FETCH_ASSOC),
                    'images' => $imagesStmt->fetchAll(PDO::FETCH_ASSOC),
                    'fisios' => $fisiosStmt->fetchAll(PDO::FETCH_ASSOC) // **NUEVO**
                ]);
                break;
        }
    } catch (Exception $e) {
        if (isset($db) && $db->inTransaction()) $db->rollBack();
        http_response_code(400);
        echo json_encode(['status' => 'error', 'message' => $e->getMessage()]);
    }
    exit;
}

$page_title = "Catàleg d'Exercicis";
include 'partials/header.php';
?>

<style>
    .media-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(120px, 1fr)); gap: 1rem; }
    .media-card { cursor: pointer; border: 2px solid transparent; border-radius: 0.375rem; transition: all 0.2s ease-in-out; background-color: #f8f9fa; }
    .media-card:hover { transform: scale(1.05); box-shadow: 0 0.125rem 0.25rem rgba(0,0,0,.075); }
    .media-card.selected { border-color: var(--bs-primary); box-shadow: 0 0 0 0.25rem rgba(var(--bs-primary-rgb), .25); }
    .media-card video, .media-card img { width: 100%; height: 80px; object-fit: cover; border-radius: 0.25rem 0.25rem 0 0; }
    .media-card .title { font-size: 0.75rem; padding: 0.5rem; text-align: center; }
    .media-embed-icon { width: 100%; height: 80px; display: flex; align-items: center; justify-content: center; background-color: #343a40; color: white; border-radius: 0.25rem 0.25rem 0 0;}

    .exercise-list-view .list-thumbnail { width: 120px; height: 67.5px; object-fit: cover; border-radius: .25rem; }
    .exercise-list-view .tags-column { max-width: 250px; white-space: normal; }

    .clear-search-btn { position: absolute; right: 0; top: 0; height: 100%; z-index: 3; display: none; background: transparent; border: none; padding: 0.375rem 0.75rem; color: #6c757d; }
    .clear-search-btn:hover { color: #212529; }

    .no-media-placeholder { background-color: #e9ecef; color: #6c757d; display: flex; flex-direction: column; align-items: center; justify-content: center; }
    .list-thumbnail.no-media-placeholder { background-color: #e9ecef; }
    .no-media-placeholder i { font-size: 2.5rem; }
    .list-thumbnail.no-media-placeholder i { font-size: 1.8rem; }
    .list-thumbnail.no-media-placeholder span { font-size: 0.65rem; margin-top: 2px; }

    .sortable-header {
        cursor: pointer;
        user-select: none;
    }
    .sortable-header .bi-arrow-down-up {
        opacity: 0.4;
    }
    .dropdown-item i.bi { margin-right: 0.5rem; }
    .dropdown .btn.dropdown-toggle:hover {
        color: #FFF !important;
    }

    /* ESTA ES LA REGLA CLAVE que ya tenías para arreglar los menús */
    td .dropdown, .card-footer .dropdown {
        position: static;
    }

    .dropdown-item.disabled, .dropdown-item:disabled {
        color: #adb5bd;
        pointer-events: none;
        background-color: transparent;
    }
    .table td.wrap-text {
        white-space: normal;
        word-wrap: break-word;
        max-width: 150px;
        font-size: 0.85rem;
        line-height: 1.3;
    }

    /* ★★★ INICIO DE LA MODIFICACIÓN PARA MÓVIL ★★★ */
    @media (max-width: 767.98px) {
        /* Ocultamos los botones de cambiar vista (Grid/List) en móvil */
        .toggle-view-btn {
            display: none !important;
        }
    }
    /* ★★★ FIN DE LA MODIFICACIÓN PARA MÓVIL ★★★ */
</style>

<main class="main-content container mt-4" style="max-width: 1420px;">
    <!-- ★★★ MODIFICACIÓN: Añadida clase 'exercises-header-bar' para CSS móvil ★★★ -->
    <div class="d-flex justify-content-between align-items-center mb-4 exercises-header-bar">
        <h4><i class="bi bi-person-arms-up me-2"></i> Catàleg d'Exercicis</h4>
        <button class="btn btn-primary" id="addExerciseBtn"><i class="bi bi-plus-circle me-2"></i> Nou Exercici</button>
    </div>

    <div class="card shadow-sm">
        <div class="card-body">

            <!-- ★★★ INICIO: Bloque de Controles Responsive (Móvil) ★★★ -->
            <div class="row g-2 mb-3">

                <!-- Columna 1 (Móvil): Switch y Dropdown -->
                <div class="col-12 col-md-auto">
                    <div class="d-flex align-items-center h-100">
                        <?php if (in_array($user_rol, ['superadmin', 'fisio'])): ?>
                        <div class="form-check form-switch me-3 text-nowrap">
                            <input class="form-check-input" type="checkbox" role="switch" id="filterMyExercises">
                            <label class="form-check-label" for="filterMyExercises">Només els meus</label>
                        </div>
                        <?php endif; ?>

                        <div class="flex-grow-1 mobile-filter-flex-grow" style="max-width: 220px;">
                            <select id="categoryFilter" class="form-select">
                                <option value="">Totes les Categories</option>
                            </select>
                        </div>
                    </div>
                </div>

                <!-- Columna 2 (Móvil): Buscador y Botones -->
                <div class="col-12 col-md">
                    <div class="d-flex align-items-center justify-content-start justify-content-md-end flex-wrap gap-2">

                        <div class="input-group mobile-filter-full-width" style="max-width: 400px; position: relative;">
                            <span class="input-group-text"><i class="bi bi-search"></i></span>
                            <input type="text" id="searchInput" class="form-control" placeholder="Cercar exercicis...">
                            <button class="clear-search-btn" type="button" id="clearSearchBtn"><i class="bi bi-x"></i></button>
                        </div>

                        <div class="btn-group mobile-filter-btn-group" role="group">
                            <button type="button" class="btn btn-outline-secondary toggle-view-btn active" id="gridViewBtn" title="Vista en Quadrícula"><i class="bi bi-grid-fill"></i></button>
                            <button type="button" class="btn btn-outline-secondary toggle-view-btn" id="listViewBtn" title="Vista en Llista"><i class="bi bi-list"></i></button>
                        </div>

                        <div class="btn-group mobile-filter-btn-group" id="sort-buttons-group">
                             <button class="btn btn-outline-secondary sort-btn active" data-sort="creation_date" data-order="DESC" title="Ordenar per Data">
                                <i class="bi bi-calendar3"></i>
                            </button>
                            <button class="btn btn-outline-secondary sort-btn" data-sort="title" data-order="ASC" title="Ordenar per Títol">
                                <i class="bi bi-sort-alpha-down"></i>
                            </button>
                        </div>
                    </div>
                </div>
            </div>
            <!-- ★★★ FIN: Bloque de Controles Responsive ★★★ -->

            <div id="exercise-library-container" class="row g-4"><div class="col-12 text-center p-5"><div class="spinner-border text-primary"></div></div></div>
            <div id="pagination-container" class="mt-4"></div>
        </div>
    </div>
</main>

<div class="modal fade" id="exerciseModal" tabindex="-1">
    <div class="modal-dialog modal-xl"><div class="modal-content">
        <div class="modal-header"><h5 class="modal-title" id="exerciseModalLabel">Crear Exercici</h5><button type="button" class="btn-close" data-bs-dismiss="modal"></button></div>
        <div class="modal-body">
            <form id="exerciseForm">
                <input type="hidden" name="id">
                <div class="row">
                    <div class="col-md-6 border-end">
                        <ul class="nav nav-tabs nav-fill mb-2" id="mediaSelectTabs" role="tablist">
                            <li class="nav-item" role="presentation"><button class="nav-link active" id="videos-select-tab" data-bs-toggle="tab" data-bs-target="#videos-select-panel" type="button">Vídeos</button></li>
                            <li class="nav-item" role="presentation"><button class="nav-link" id="images-select-tab" data-bs-toggle="tab" data-bs-target="#images-select-panel" type="button">Imatges</button></li>
                        </ul>
                        <div class="d-flex justify-content-between align-items-center mb-3">
                            <div class="form-check form-switch"><input class="form-check-input" type="checkbox" role="switch" id="filterMyMediaModal"><label class="form-check-label" for="filterMyMediaModal">Només els meus</label></div>
                            <div class="flex-grow-1 ms-3"><input type="text" id="mediaSearchInput" class="form-control" placeholder="Cercar medi..."></div>
                        </div>
                        <div class="tab-content">
                            <div class="tab-pane fade show active" id="videos-select-panel" role="tabpanel">
                                <div id="video-grid-container" class="p-2 border rounded" style="max-height: 400px; overflow-y: auto;"></div>
                            </div>
                            <div class="tab-pane fade" id="images-select-panel" role="tabpanel">
                                 <div id="image-grid-container" class="p-2 border rounded" style="max-height: 400px; overflow-y: auto;"></div>
                            </div>
                        </div>
                        <input type="hidden" id="selectedVideoId" name="id_video">
                        <input type="hidden" id="selectedImageId" name="id_image">
                    </div>
                    <div class="col-md-6">
                        <div id="selected-media-info" class="alert p-2 small mb-3"></div>
                        <div class="mb-3"><label class="form-label">Títol <span class="text-danger">*</span></label><input type="text" class="form-control" name="title" required></div>
                        <div class="mb-3"><label class="form-label">Fisios Col·laboradors</label><select id="fisio-colab-select" name="assigned_fisios[]" multiple></select></div>

                        <div class="row mb-3 gx-1">
                                                    <div class="col">
                                                        <div class="input-group">
                                                            <span class="input-group-text px-2" data-bs-toggle="tooltip" title="Sèries">
                                                                <i class="bi bi-arrow-repeat"></i>
                                                            </span>
                                                            <input type="text" class="form-control px-1 text-center" name="series" placeholder="Ex: 3" required>
                                                        </div>
                                                    </div>
                                                    <div class="col">
                                                        <div class="input-group">
                                                            <span class="input-group-text px-2" data-bs-toggle="tooltip" title="Repeticions">
                                                                <i class="bi bi-stopwatch"></i>
                                                            </span>
                                                            <input type="text" class="form-control px-1 text-center" name="repetitions" placeholder="Ex: 10" required>
                                                        </div>
                                                    </div>
                                                    <div class="col">
                                                        <div class="input-group">
                                                            <span class="input-group-text px-2" data-bs-toggle="tooltip" title="Descans">
                                                                <i class="bi bi-clock-history"></i>
                                                            </span>
                                                            <input type="text" class="form-control px-1 text-center" name="rest_time" placeholder="Ex: 60s" required>
                                                        </div>
                                                    </div>
                                                </div>

                        <div class="mb-3"><label class="form-label">Categoria Principal <span class="text-danger">*</span></label><select id="category-select" name="id_categoria" required></select></div>
                        <div class="mb-3"><label class="form-label">Etiquetes <span class="text-danger">*</span></label><select id="tags-select" name="tags" multiple required></select></div>
                        <div class="mb-3"><label class="form-label">Notes per al pacient</label><textarea class="form-control" name="notes" rows="4"></textarea></div>
                    </div>
                </div>
                <div class="modal-footer mt-3"><button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Cancel·lar</button><button type="submit" class="btn btn-primary">Guardar Exercici</button></div>
            </form>
        </div>
    </div></div>
</div>

<div class="modal fade" id="manageModal" tabindex="-1">
    <div class="modal-dialog"><div class="modal-content">
        <div class="modal-header"><h5 class="modal-title" id="manageModalLabel"></h5><button type="button" class="btn-close" data-bs-dismiss="modal"></button></div>
        <div class="modal-body" id="manageModalBody"></div>
        <div class="modal-footer"><button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Cancel·lar</button><button type="button" class="btn btn-warning" id="archiveBtn">Arxivar</button><button type="button" class="btn btn-danger" id="deleteBtn">Eliminar</button></div>
    </div></div>
</div>

<div class="modal fade" id="viewExerciseModal" tabindex="-1">
    <div class="modal-dialog modal-lg modal-dialog-scrollable">
        <div class="modal-content">
            <div class="modal-header"><h5 class="modal-title" id="viewExerciseModalLabel"></h5><button type="button" class="btn-close" data-bs-dismiss="modal"></button></div>
            <div class="modal-body" id="viewExerciseModalBody"></div>
            <div class="modal-footer"><button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Tancar</button></div>
        </div>
    </div>
</div>

<div class="modal fade" id="cloneExerciseModal" tabindex="-1">
    <div class="modal-dialog">
        <div class="modal-content">
            <div class="modal-header"><h5 class="modal-title" id="cloneExerciseModalLabel">Clonar Exercici</h5><button type="button" class="btn-close" data-bs-dismiss="modal"></button></div>
            <div class="modal-body">
                <form id="cloneExerciseForm">
                    <input type="hidden" name="original_exercise_id">
                    <p>Es crearà una còpia d'aquest exercici. Per favor, confirma el nou títol.</p>
                    <div class="mb-3"><label class="form-label">Nou Títol de l'Exercici</label><input type="text" name="title" class="form-control" required></div>
                    <div class="modal-footer"><button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Cancel·lar</button><button type="submit" class="btn btn-primary"><i class="bi bi-copy"></i> Confirmar Clonació</button></div>
                </form>
            </div>
        </div>
    </div>
</div>

<?php include 'partials/footer.php'; ?>

<script>
    const USER_VIEW_PREFERENCES = <?php echo $user_view_prefs_json; ?>;
</script>
<script>
// Función de utilidad para mostrar toasts (asumiendo que existe en 'partials/footer.php' o un script cargado)
function showToast(message, type) {
    console.log(`Toast (${type}): ${message}`);
    // Aquí iría la lógica real de tu función showToast
}

$(document).ready(function() {

    function isMobileView() {
        // Usamos el breakpoint 'md' de Bootstrap
        return window.innerWidth < 767.98;
    }

    const CURRENT_USER_ID = <?= $user_id ?>;
    const IS_SUPERADMIN = '<?= $user_rol ?>' === 'superadmin';
    const FILTER_MINE_DEFAULT = <?= $filtro_defecto ?> == 1;
    const exerciseModal = new bootstrap.Modal('#exerciseModal');
    const manageModal = new bootstrap.Modal('#manageModal');
    const viewExerciseModal = new bootstrap.Modal('#viewExerciseModal');
    const cloneExerciseModal = new bootstrap.Modal('#cloneExerciseModal');
    let itemToManage = { id: null, name: '', ownerId: null };

    // **** MODIFICAT: El viewMode ara llegeix la preferència de l'usuari ****
    const initialExerciseView = USER_VIEW_PREFERENCES['exercises'] || 'grid'; // Clau per a exercicis

    let appState = {
        page: 1,
        search: '',
        sort: 'creation_date',
        order: 'DESC',
        filterMine: FILTER_MINE_DEFAULT,
    viewMode: isMobileView() ? 'grid' : initialExerciseView, // <-- MODIFICADO: Forzar 'grid' en móvil
        categoryId: '' // <-- ★★★ AÑADIR ESTA LÍNEA ★★★
    };

    // --- INICIO MODIFICACIÓN: Leer filtro de URL ---
        const urlParams_ex = new URLSearchParams(window.location.search);
        if (urlParams_ex.get('filter') === 'mine') {
            appState.filterMine = true;
        }
        // --- FIN MODIFICACIÓN ---

    // **MODIFICADO**: Añadido 'allFisios'
    let allCategories = [], allTags = [], allVideos = [], allImages = [], allFisios = [];
    // **MODIFICADO**: Añadido 'fisioColabSelect'
    let tagsSelect, categorySelect, fisioColabSelect; // TomSelect instances

    new bootstrap.Tooltip(document.body, { selector: "[data-bs-toggle='tooltip']" });

    // **NUEVO**: Helper para escapar HTML
    function escapeHtml(text) {
        if (typeof text !== 'string') return '';
        const map = { '&': '&amp;', '<': '&lt;', '>': '&gt;', '"': '&quot;', "'": '&#039;' };
        return text.replace(/[&<>"']/g, m => map[m]);
    }

    function getImagePath(filename) {
        if (!filename) return '';
        const systemImages = ['logo.jpg', 'logo2.jpg', 'img_defecte.jpg'];
        const folder = systemImages.includes(filename) ? 'logos/' : 'images/';
        return `${folder}${filename}`;
    }

    function getInitialSortIcon(currentSort, currentOrder, columnName) {
        if (currentSort === columnName) {
            return currentOrder === 'ASC' ? '<i class="bi bi-caret-up-fill ms-2"></i>' : '<i class="bi bi-caret-down-fill ms-2"></i>';
        }
        return '<i class="bi bi-arrow-down-up ms-2 text-muted opacity-50"></i>';
    }

    function setupSearch(inputId, clearBtnId, state, fetchFunction) {
        let searchTimeout;
        $(inputId).on('keyup', function() {
            $(clearBtnId).toggle($(this).val().length > 0);
            clearTimeout(searchTimeout);
            searchTimeout = setTimeout(() => {
                state.search = $(this).val();
                state.page = 1;
                fetchFunction();
            }, 300);
        });
        $(clearBtnId).on('click', () => $(inputId).val('').trigger('keyup').focus());
    }

    // --- ★ TAREA 4 (Spinner Suave) ---
    function fetchExercises() {
        // ATENUAMOS la lista, no la borramos
        $('#exercise-library-container').css('opacity', 0.5);

        return $.getJSON('exercises.php', { ajax: true, action: 'read', ...appState })
        .done(response => {
            $('#exercise-library-container').css('opacity', 1); // RESTAURAMOS
            if(response.status === 'success') {
                renderExercises(response.data, response.pagination.currentSort, response.pagination.currentOrder);
                renderPagination(response.pagination);
                updateSortButtons(response.pagination.currentSort, response.pagination.currentOrder);
            }
        })
        .fail(() => {
            $('#exercise-library-container').css('opacity', 1).html('<div class="col-12"><div class="alert alert-danger text-center">Error en carregar els exercicis.</div></div>');
        });
    }
    // --- ★ FIN TAREA 4 ---

    function fetchFormDependencies() {
        $.getJSON('exercises.php', { ajax: true, action: 'get_form_dependencies' })
        .done(response => {
            allCategories = response.categories;
            allTags = response.tags;
            allVideos = response.videos;
            allImages = response.images;
            allFisios = response.fisios; // **NUEVO**

            // ★★★ AÑADIR ESTE BLOQUE PARA POBLAR EL FILTRO ★★★
            const mainCategoryFilter = $('#categoryFilter');
            mainCategoryFilter.html('<option value="">Totes les Categories</option>');
            // Filtrar y ordenar padres
            const parents = allCategories.filter(c => !c.parent_id);
            parents.sort((a, b) => a.name.localeCompare(b.name));

            parents.forEach(p => {
                mainCategoryFilter.append(new Option(p.name, p.id)); // Añadir padre
                // Encontrar y ordenar hijos
                const children = allCategories.filter(c => c.parent_id == p.id);
                children.sort((a, b) => a.name.localeCompare(b.name));
                children.forEach(c => {
                    mainCategoryFilter.append(new Option(`↳ ${c.name}`, c.id)); // Añadir hijo
                });
            });
            // ★★★ FIN ★★★

            fetchExercises();
        });
    }

    // --- ★ TAREA 2 (Limpieza UI) ---
    // Modificado para no iluminar nada por defecto si no hay match
    function updateSortButtons(currentSort, currentOrder) {
        $('#sort-buttons-group .sort-btn').removeClass('active');

        // Solo ilumina si estamos en Grid Y hay un botón que coincide
        if (appState.viewMode === 'grid') {
             const targetButton = $(`#sort-buttons-group .sort-btn[data-sort="${currentSort}"]`);
             if (targetButton.length > 0) {
                 targetButton.addClass('active');
             }
        }
    }
    // --- ★ FIN TAREA 2 ---

    function renderExercises(exercises, currentSort, currentOrder) {
            const container = $('#exercise-library-container');
            container.empty();
            if (exercises.length === 0) { container.html('<div class="col-12"><div class="alert alert-secondary text-center">No s\'han trobat exercicis.</div></div>'); return; }

            if (appState.viewMode === 'grid') {
                container.removeClass('table-responsive').addClass('row g-4');
                exercises.forEach(ex => {
                    let mediaHtml = '';
                    if (ex.video_filename) {
                        const isEmbed = ex.video_filename.startsWith('http');

                        if (isEmbed) {
                            // Comprobamos si es YouTube para usar iframe, si no, video tag
                            const ytMatch = ex.video_filename.match(/youtube\.com\/embed\/([a-zA-Z0-9\-_]+)/);

                            if (ytMatch) {
                                // Es YouTube -> Iframe
                                mediaHtml = `<iframe src="${ex.video_filename}" class="w-100 h-100" style="border:0;" allowfullscreen></iframe>`;
                            } else {
                                // CORRECCIÓN: Video externo directo (MP4/WebM) -> Video Tag
                                mediaHtml = `<video oncontextmenu="return false;" controlsList="nodownload" preload="metadata" src="${ex.video_filename}#t=0.5" class="w-100 h-100" style="object-fit: cover;"></video><i class="bi bi-play-circle-fill fs-1 text-white position-absolute" style="top:50%; left:50%; transform:translate(-50%,-50%); opacity:0.7;"></i>`;
                            }
                        } else {
                            // Video local -> Video Tag
                            mediaHtml = `<video oncontextmenu="return false;" controlsList="nodownload" preload="metadata" src="videos/${ex.video_filename}#t=0.5" class="w-100 h-100" style="object-fit: cover;"></video><i class="bi bi-play-circle-fill fs-1 text-white position-absolute" style="top:50%; left:50%; transform:translate(-50%,-50%); opacity:0.7;"></i>`;
                        }
                    } else if (ex.image_filename) {
                        mediaHtml = `<img src="${getImagePath(ex.image_filename)}" class="w-100 h-100" style="object-fit:cover;" alt="${ex.title}">`;
                    } else {
                        mediaHtml = `<div class="w-100 h-100 no-media-placeholder d-flex align-items-center justify-content-center">
                                        <div class="text-center">
                                            <i class="bi bi-camera-video-off fs-1"></i>
                                            <p class="mb-0 mt-2 small">Sense medis associats</p>
                                        </div>
                                    </div>`;
                    }

                    const collaboratorsHtml_grid = ex.collaborators ? `<br>Col·laboren: ${escapeHtml(ex.collaborators)}` : '';

                    container.append(`<div class="col-md-6 col-lg-3"><div class="card h-100 shadow-sm">
                        <div class="card-img-top ratio ratio-16x9 bg-dark position-relative">${mediaHtml}</div>
                        <div class="card-body pb-2 d-flex flex-column">
                            <h5 class="card-title">${escapeHtml(ex.title)}</h5>
                            <div class="mb-2">${ex.category_name ? `<span class="badge bg-primary">${escapeHtml(ex.category_name)}</span>` : ''}</div>
                            <div class="mt-auto small text-muted">${ex.tags.map(tag => `<span class="badge bg-secondary me-1">${escapeHtml(tag.name)}</span>`).join('') || '&nbsp;'}</div>
                        </div>
                        <ul class="list-group list-group-flush small"><li class="list-group-item d-flex justify-content-around text-center"><div><strong>Sèries</strong><br>${escapeHtml(ex.series) || 'N/A'}</div><div><strong>Reps</strong><br>${escapeHtml(ex.repetitions) || 'N/A'}</div><div><strong>Descans</strong><br>${escapeHtml(ex.rest_time) || 'N/A'}</div></li></ul>
                        <div class="card-footer d-flex justify-content-between align-items-center">
                            <small class="text-muted" style="line-height: 1.3; max-width: 70%;">Creat per: ${escapeHtml(ex.creator_name)} ${escapeHtml(ex.creator_surname)}${collaboratorsHtml_grid}</small>
                            ${renderCardButtons(ex)}
                        </div>
                    </div></div>`);
                });
            } else {
                container.removeClass('row g-4').addClass('table-responsive');
                let tableHtml = `<table class="table table-hover align-middle exercise-list-view">
                    <thead>
                        <tr>
                            <th style="width: 150px;">Recurs</th>
                            <th class="sortable-header" data-sort="title">Títol${getInitialSortIcon(currentSort, currentOrder, 'title')}</th>
                            <th class="sortable-header" data-sort="category_name">Categoria${getInitialSortIcon(currentSort, currentOrder, 'category_name')}</th>
                            <th>Etiquetes</th>
                            <th class="sortable-header" data-sort="creator_surname" style="width: 15%;">Creat per${getInitialSortIcon(currentSort, currentOrder, 'creator_surname')}</th>
                            <th style="width: 15%;">Col·laboradors</th>
                            <th class="sortable-header" data-sort="creation_date" style="width: 10%;">Data${getInitialSortIcon(currentSort, currentOrder, 'creation_date')}</th>
                            <th class="text-end" style="width: 10%;">Accions</th>
                        </tr>
                    </thead>
                    <tbody>`;

                exercises.forEach(ex => {
                    let thumbnailHtml = '';
                    if (ex.video_filename) {
                        const isEmbed = ex.video_filename.startsWith('http');

                        if (isEmbed) {
                            const ytMatch = ex.video_filename.match(/youtube\.com\/embed\/([a-zA-Z0-9\-_]+)/);
                            if (ytMatch) {
                                // Es YouTube -> Miniatura de imagen
                                thumbnailHtml = `<img src="https://img.youtube.com/vi/${ytMatch[1]}/mqdefault.jpg" class="list-thumbnail">`;
                            } else {
                                // CORRECCIÓN: Es URL Externa Directa (MP4) -> Miniatura de Video
                                thumbnailHtml = `<video src="${ex.video_filename}#t=0.5" class="list-thumbnail" preload="metadata"></video>`;
                            }
                        } else {
                             // Es Video Local -> Miniatura de Video
                            thumbnailHtml = `<video src="videos/${ex.video_filename}#t=0.5" class="list-thumbnail"></video>`;
                        }
                    } else if (ex.image_filename) {
                         thumbnailHtml = `<img src="${getImagePath(ex.image_filename)}" class="list-thumbnail">`;
                    } else {
                        thumbnailHtml = `<div class="list-thumbnail no-media-placeholder d-flex align-items-center justify-content-center">
                                            <div class="text-center">
                                                <i class="bi bi-camera-video-off fs-4"></i>
                                                <span class="d-block small" style="font-size: 0.65rem;">Sense medis</span>
                                            </div>
                                        </div>`;
                    }

                    const collaboratorsCell = `<td class="small wrap-text">${escapeHtml(ex.collaborators) || 'Cap'}</td>`;
                    const createdDate = ex.creation_date ? new Date(ex.creation_date).toLocaleDateString('ca-ES', { day: '2-digit', month: '2-digit', year: 'numeric' }) : 'N/A';

                    tableHtml += `<tr>
                        <td>${thumbnailHtml}</td>
                        <td><strong>${escapeHtml(ex.title)}</strong></td>
                        <td>${escapeHtml(ex.category_name) || ''}</td>
                        <td class="tags-column">${ex.tags.map(tag => `<span class="badge bg-secondary me-1">${escapeHtml(tag.name)}</span>`).join('')}</td>
                        <td>${escapeHtml(ex.creator_name)} ${escapeHtml(ex.creator_surname)}</td>
                        ${collaboratorsCell}
                        <td class="small text-nowrap">${createdDate}</td>
                        <td class="text-end">${renderCardButtons(ex)}</td>
                    </tr>`;
                });
                container.html(tableHtml + '</tbody></table>');
            }
        }

    // **INICIO MODIFICACIÓN**: Lógica de botones deshabilitados
    function renderCardButtons(ex) {
        const isCreator = ex.id_creator == CURRENT_USER_ID;
        const collaboratorIdsArray = ex.collaborator_ids ? ex.collaborator_ids.split(',') : [];
        const isCollaborator = collaboratorIdsArray.includes(String(CURRENT_USER_ID));

        // canModify: Para Editar (Creador, Colaborador, Superadmin)
        const canModify = IS_SUPERADMIN || isCreator || isCollaborator;
        // canManage: Para Arxivar/Eliminar (Solo Creador o Superadmin)
        const canManage = IS_SUPERADMIN || isCreator;

        const titleAttr = ex.title ? escapeHtml(ex.title) : '';
        const manage_data = `data-id="${ex.id}" data-name="${titleAttr}" data-owner-id="${ex.id_creator}"`;

        let editButtonHtml = `<li><a class="dropdown-item edit-btn ${!canModify ? 'disabled' : ''}"
                                   href="#"
                                   data-id="${ex.id}"
                                   ${!canModify ? 'aria-disabled="true" tabindex="-1"' : ''}>
                                   <i class="bi bi-pencil"></i> Editar
                                </a></li>`;

        let manageButtonHtml = `<li><a class="dropdown-item manage-btn ${!canManage ? 'disabled' : ''}"
                                     href="#"
                                     ${manage_data}
                                     ${!canManage ? 'aria-disabled="true" tabindex="-1"' : ''}>
                                     <i class="bi bi-shield-slash"></i> Arxivar / Eliminar
                                  </a></li>`;

        return `
            <div class="dropdown">
                <button class="btn btn-sm btn-outline-secondary dropdown-toggle" type="button" data-bs-toggle="dropdown" aria-expanded="false" title="Gestionar Exercici">
                    <i class="bi bi-gear-fill"></i>
                </button>
                <ul class="dropdown-menu dropdown-menu-end">
                    <li><a class="dropdown-item view-exercise-btn" href="#" data-id="${ex.id}"><i class="bi bi-eye"></i> Veure Detalls</a></li>
                    <li><hr class="dropdown-divider"></li>
                    ${editButtonHtml}
                    <li><a class="dropdown-item clone-btn" href="#" data-id="${ex.id}" data-title="${titleAttr}"><i class="bi bi-copy"></i> Clonar</a></li>
                    <li><hr class="dropdown-divider"></li>
                    ${manageButtonHtml}
                </ul>
            </div>
        `;
    }
    // **FIN MODIFICACIÓN**

    function renderPagination(pagination) {
        const container = $('#pagination-container');
        container.empty();
        if (pagination.totalPages <= 1) return;
        let paginationHtml = `<nav><ul class="pagination justify-content-center">`;
        for (let i = 1; i <= pagination.totalPages; i++) { paginationHtml += `<li class="page-item ${i === pagination.currentPage ? 'active' : ''}"><a class="page-link" href="#" data-page="${i}">${i}</a></li>`; }
        container.html(paginationHtml + '</ul></nav>');
    }

    // **MODIFICADO**: Añadida inicialización de 'fisioColabSelect'
    function initializeSelects(catOptions, catOptgroups, tOptions, tOptgroups, fOptions) {
        // Destruir instancias existentes si las hay
        if (categorySelect) categorySelect.destroy();
        if (tagsSelect) tagsSelect.destroy();
        if (fisioColabSelect) fisioColabSelect.destroy();

        categorySelect = new TomSelect('#category-select', {
            placeholder: 'Selecciona...',
            options: catOptions,
            optgroups: catOptgroups,
            render: {
                option: (d,e) => `<div class="py-2 px-3">${e(d.text)}</div>`,
                optgroup_header: (d,e) => `<div class="fs-6 fw-bold text-muted p-2">${e(d.label)}</div>`
            }
        });

        tagsSelect = new TomSelect('#tags-select', {
            placeholder: 'Selecciona...',
            plugins: ['remove_button'],
            options: tOptions,
            optgroups: tOptgroups,
            render: {
                option: (d,e) => `<div class="py-2 px-3">${e(d.text)}</div>`,
                optgroup_header: (d,e) => `<div class="fs-6 fw-bold text-muted p-2">${e(d.label)}</div>`
            }
        });

        fisioColabSelect = new TomSelect('#fisio-colab-select', {
            placeholder: 'Afig col·laboradors...',
            plugins: ['remove_button'],
            options: fOptions,
            render: {
                option: (d,e) => `<div class="py-2 px-3">${e(d.text)}</div>`,
            }
        });
    }

    // **MODIFICADO**: Gestionar el modal de colaboradores
    function openExerciseModal(exerciseData = null) {
        const form = $('#exerciseForm')[0];
        form.reset();
        $('#exerciseModalLabel').text(exerciseData ? 'Editar Exercici' : 'Crear Exercici');
        $(form).find('[name="id"]').val(exerciseData ? exerciseData.id : '');
        $('#selectedVideoId').val(exerciseData ? exerciseData.id_video : '');
        $('#selectedImageId').val(exerciseData ? exerciseData.id_image : '');
        $('#filterMyMediaModal').prop('checked', false);
        $('#mediaSearchInput').val('');

        // Preparar opciones de TomSelect
        const catOptgrps = allCategories.filter(c => c.parent_id === null || c.parent_id === '0').map(p => ({ value: `cat-${p.id}`, label: p.name }));
        const catOpts = allCategories.filter(c => c.parent_id !== null && c.parent_id !== '0').map(c => ({ value: c.id, text: c.name, optgroup: `cat-${c.parent_id}` }));

        const tagOptgrps = allTags.filter(t => t.parent_id === null || t.parent_id === '0').map(p => ({ value: `tag-${p.id}`, label: p.name }));
        const tagOpts = allTags.filter(t => t.parent_id !== null && t.parent_id !== '0').map(t => ({ value: t.id, text: t.name, optgroup: `tag-${t.parent_id}` }));

        const fOpts = allFisios.map(f => ({value: f.id, text: `${f.apellido}, ${f.nombre}`}));

        initializeSelects(catOpts, catOptgrps, tagOpts, tagOptgrps, fOpts);

        if (exerciseData) {
            $(form).find('[name="title"]').val(exerciseData.title); $(form).find('[name="series"]').val(exerciseData.series); $(form).find('[name="repetitions"]').val(exerciseData.repetitions); $(form).find('[name="rest_time"]').val(exerciseData.rest_time); $(form).find('[name="notes"]').val(exerciseData.notes);

            if (categorySelect) categorySelect.setValue(exerciseData.id_categoria);
            if (tagsSelect) tagsSelect.setValue(exerciseData.tags_ids);

            // **NUEVO**: Poblar y gestionar permisos de colaboradores
            if (fisioColabSelect) {
                fisioColabSelect.setValue(exerciseData.assigned_fisios);
                const isCreatorOrAdmin = IS_SUPERADMIN || exerciseData.id_creator == CURRENT_USER_ID;
                if (isCreatorOrAdmin) {
                    fisioColabSelect.enable();
                } else {
                    fisioColabSelect.disable();
                }
            }

            if (exerciseData.id_video) {
                new bootstrap.Tab($('#videos-select-tab')).show();
            } else if (exerciseData.id_image) {
                new bootstrap.Tab($('#images-select-tab')).show();
            }
        } else {
             // **NUEVO**: Asegurar que está habilitado al crear
             if (fisioColabSelect) fisioColabSelect.enable();
        }

        updateMediaGrids();
        updateSelectedMediaDisplay();
        exerciseModal.show();
    }

    function updateMediaGrids() {
        const filterMine = $('#filterMyMediaModal').is(':checked');
        const searchTerm = $('#mediaSearchInput').val().toLowerCase();

        let videosToRender = allVideos.filter(v => (!filterMine || v.id_uploader == CURRENT_USER_ID) && v.title.toLowerCase().includes(searchTerm));
        renderVideoGrid(videosToRender);

        let imagesToRender = allImages.filter(i => (!filterMine || i.id_uploader == CURRENT_USER_ID) && i.title.toLowerCase().includes(searchTerm));
        renderImageGrid(imagesToRender);
    }

    function renderVideoGrid(videos) {
            const gridContainer = $('#video-grid-container').html('<div class="media-grid"></div>');
            const grid = gridContainer.find('.media-grid');

            if (videos.length === 0) {
                gridContainer.html('<p class="text-muted text-center">No s\'han trobat vídeos.</p>');
                return;
            }

            const selectedId = $('#selectedVideoId').val();

            videos.forEach(video => {
                const isEmbed = video.filename.startsWith('http');
                let thumbnailHtml;

                if (isEmbed) {
                    // Comprobar si es YouTube
                    const ytMatch = video.filename.match(/youtube\.com\/embed\/([a-zA-Z0-9\-_]+)/);

                    if (ytMatch) {
                        // Es YouTube -> Imagen
                        thumbnailHtml = `<img src="https://img.youtube.com/vi/${ytMatch[1]}/mqdefault.jpg" alt="Miniatura">`;
                    } else {
                        // ★ AQUÍ ESTÁ EL CAMBIO PARA TU CAPTURA ★
                        // Antes aquí había un div con clase "media-embed-icon".
                        // Lo cambiamos por la etiqueta <video> para que se vea la imagen real.
                        thumbnailHtml = `<video preload="metadata" src="${video.filename}#t=0.5" muted playsinline></video>`;
                    }
                } else {
                    // Video Local -> Video Tag
                    thumbnailHtml = `<video preload="metadata" src="videos/${video.filename}#t=0.5" muted playsinline></video>`;
                }

                grid.append(`<div class="media-card ${video.id == selectedId ? 'selected' : ''}" data-media-id="${video.id}" data-media-title="${escapeHtml(video.title)}">${thumbnailHtml}<div class="title text-truncate">${escapeHtml(video.title)}</div></div>`);
            });
        }

    function renderImageGrid(images) {
        const gridContainer = $('#image-grid-container').html('<div class="media-grid"></div>');
        const grid = gridContainer.find('.media-grid');
        if (images.length === 0) { gridContainer.html('<p class="text-muted text-center">No s\'han trobat imatges.</p>'); return; }
        const selectedId = $('#selectedImageId').val();
        images.forEach(image => {
            const thumbnailHtml = `<img src="${getImagePath(image.filename)}" alt="${escapeHtml(image.title)}">`;
            grid.append(`<div class="media-card ${image.id == selectedId ? 'selected' : ''}" data-media-id="${image.id}" data-media-title="${escapeHtml(image.title)}">${thumbnailHtml}<div class="title text-truncate">${escapeHtml(image.title)}</div></div>`);
        });
    }

    function updateSelectedMediaDisplay() {
        const selectedVideoId = $('#selectedVideoId').val();
        const selectedImageId = $('#selectedImageId').val();
        const infoBox = $('#selected-media-info');

        let selectedMedia = null;
        if (selectedVideoId) {
            selectedMedia = allVideos.find(v => v.id == selectedVideoId);
        } else if (selectedImageId) {
            selectedMedia = allImages.find(i => i.id == selectedImageId);
        }

        if (selectedMedia) {
            infoBox.html(`<strong>MEDI ASSIGNAT:</strong> ${escapeHtml(selectedMedia.title)}`).removeClass('alert-secondary').addClass('alert-info');
        } else {
            infoBox.html("<strong>SENSE MEDI ASSIGNAT</strong>").removeClass('alert-info').addClass('alert-secondary');
        }
    }

    // El listener del botón 'Nou Exercici' (addExerciseBtn) es correcto:
    $('#addExerciseBtn').on('click', () => openExerciseModal());

    // **MODIFICADO**: Respetar 'disabled'
    $(document).on('click', '.edit-btn', function(e) {
        e.preventDefault();
        if ($(this).is(':disabled') || $(this).hasClass('disabled')) return;
        $.getJSON('exercises.php', { ajax: true, action: 'get_exercise', id: $(this).data('id') }).done(res => openExerciseModal(res.data));
    });

    $(document).on('click', '.view-exercise-btn', function(e) {
        e.preventDefault();
        const exerciseId = $(this).data('id');
        $('#viewExerciseModalLabel').text('Carregant...');
        $('#viewExerciseModalBody').html('<div class="text-center p-5"><div class="spinner-border"></div></div>');
        viewExerciseModal.show();

        $.getJSON('exercises.php', { ajax: true, action: 'get_exercise', id: exerciseId })
        .done(response => {
            if (response.status === 'success') {
                const ex = response.data;
                $('#viewExerciseModalLabel').text(escapeHtml(ex.title));
                let playerHtml = '';
                if (ex.video_filename) {
                    const isEmbed = ex.video_filename.startsWith('http');
                    const videoSrc = isEmbed ? ex.video_filename : `videos/${ex.video_filename}`;
                    playerHtml = isEmbed ? `<iframe src="${videoSrc}" class="w-100" style="aspect-ratio: 16/9;" frameborder="0" allowfullscreen></iframe>` : `<video controls controlsList="nodownload" preload="metadata" src="${videoSrc}" class="w-100"></video>`;
                } else if (ex.image_filename) {
                    playerHtml = `<div class="ratio ratio-16x9 bg-dark rounded"><img src="${getImagePath(ex.image_filename)}" style="object-fit: contain; width: 100%; height: 100%;" alt="${escapeHtml(ex.title)}"></div>`;
                } else {
                    playerHtml = `<div class="ratio ratio-16x9 rounded" style="background-color: #e9ecef; border: 1px dashed #ced4da;">
                                      <div class="d-flex align-items-center justify-content-center h-100">
                                          <div class="text-center text-muted">
                                              <i class="bi bi-camera-video-off fs-1"></i>
                                              <p class="mb-0 mt-2 fw-bold">EXERCICI SENSE MEDIS ASSOCIATS</p>
                                          </div>
                                      </div>
                                  </div>`;
                }

                // **NUEVO**: Mostrar colaboradores en modal de vista
                let collaboratorsHtml = '';
                if (ex.assigned_fisios && ex.assigned_fisios.length > 0) {
                     let colabNames = [];
                     ex.assigned_fisios.forEach(fisioId => {
                         if (fisioId != ex.id_creator) {
                            const fisio = allFisios.find(f => f.id == fisioId);
                            if (fisio) {
                                colabNames.push(`${escapeHtml(fisio.nombre)} ${escapeHtml(fisio.apellido)}`);
                            }
                         }
                     });
                     if (colabNames.length > 0) {
                        collaboratorsHtml = `<li class="list-group-item"><strong>Col·laboradors:</strong> ${colabNames.join(', ')}</li>`;
                     }
                }

                let detailsHtml = `
                    <li class="list-group-item"><strong>Pauta:</strong> ${escapeHtml(ex.series)} series de ${escapeHtml(ex.repetitions)} reps, amb ${escapeHtml(ex.rest_time)} de descans.</li>
                    <li class="list-group-item"><strong>Categoria:</strong> ${escapeHtml(ex.category_name) || 'No especificada'}</li>
                    <li class="list-group-item"><strong>Etiquetes:</strong> ${ex.tags.map(t => `<span class="badge bg-secondary me-1">${escapeHtml(t.name)}</span>`).join(' ')}</li>`;

                if (ex.creator_name && ex.creator_surname) {
                     detailsHtml += `<li class="list-group-item"><strong>Creat per:</strong> ${escapeHtml(ex.creator_name)} ${escapeHtml(ex.creator_surname)}</li>`;
                }

                detailsHtml += collaboratorsHtml; // Añadir colaboradores

                if(ex.notes) {
                    detailsHtml += `<li class="list-group-item"><strong>Notes per al pacient:</strong><br><p class="text-muted mb-0">${escapeHtml(ex.notes)}</p></li>`;
                }
                detailsHtml += `</ul>`;

                $('#viewExerciseModalBody').html(playerHtml + detailsHtml);
            }
        }).fail(() => $('#viewExerciseModalBody').html('<div class="alert alert-danger">No s\'ha pogut carregar l\'exercici.</div>'));
    });

    // --- ★ TAREA 2 (Limpieza UI) ---
    // Modificado para ocultar/mostrar botones
    $('.toggle-view-btn').on('click', function() {
        const newViewMode = $(this).attr('id') === 'gridViewBtn' ? 'grid' : 'list';
        if (appState.viewMode === newViewMode) return; // No fer res si ja està actiu

        appState.viewMode = newViewMode;
        $('.toggle-view-btn').removeClass('active');
        $(this).addClass('active');

        // --- ★ INICIO DE LA MODIFICACIÓN ★ ---
        if (newViewMode === 'list') {
            $('#sort-buttons-group').hide(); // Ocultar botones en Lista
        } else {
            $('#sort-buttons-group').show(); // Mostrar botones en Rejilla
        }
        // --- ★ FIN DE LA MODIFICACIÓN ★ ---

        // Guardar la preferència
        $.post('dashboard.php', {
            ajax: true,
            action: 'save_view_preference',
            page_name: 'exercises', // Clau per a exercicis
            view_mode: newViewMode
        }, 'json')
        .done(res => {
            if(res.status === 'success') { console.log('Vista guardada: exercises -> ' + newViewMode); }
        })
        .fail(xhr => {
             console.error('Error guardant la preferència de vista.', xhr.responseText);
        });

        fetchExercises(); // Recarregar la vista
    });
    // --- ★ FIN TAREA 2 ---


    $('#exerciseForm').on('submit', function(e) {
        e.preventDefault();
        if (!categorySelect || !categorySelect.getValue()) { showToast('Cal seleccionar una categoria principal.', 'warning'); return; }
        if (!tagsSelect || !tagsSelect.getValue() || tagsSelect.getValue().length === 0) { showToast('Cal seleccionar almenys una etiqueta.', 'warning'); return; }

        const action = $(this).find('[name="id"]').val() ? 'update' : 'create';
        let formData = new FormData(this);
        formData.append('ajax', 'true'); formData.append('action', action);
        formData.set('tags', tagsSelect.getValue().join(','));
        // **NUEVO**: Asegurarse de que 'assigned_fisios' se envía aunque esté deshabilitado
        if (fisioColabSelect && fisioColabSelect.isDisabled) {
             const fisioIds = fisioColabSelect.getValue();
             fisioIds.forEach(id => formData.append('assigned_fisios[]', id));
        }

        $.ajax({ url: 'exercises.php', type: 'POST', data: formData, processData: false, contentType: false, dataType: 'json' })
        // --- ★ TAREA 5 (Flash Suave) ---
        .done(res => {
            if(res.status === 'success'){
                showToast(res.message, 'success');
                exerciseModal.hide();

                const idToHighlight = res.saved_exercise_id; // <-- CAPTURE ID

                // Call fetchExercises() and wait for it to finish
                fetchExercises().done(() => {
                    if (idToHighlight) {
                        let elementToFlash;
                        if (appState.viewMode === 'grid') {
                            elementToFlash = $(`.manage-btn[data-id="${idToHighlight}"]`).closest('.card');
                        } else {
                            elementToFlash = $(`tr .manage-btn[data-id="${idToHighlight}"]`).closest('tr');
                        }

                        if (typeof flashElement === 'function' && elementToFlash && elementToFlash.length > 0) {
                            setTimeout(() => { // Delay para fluidez
                                flashElement(elementToFlash);
                            }, 50);
                        }
                    }
                });
            }
        })
        // --- ★ FIN TAREA 5 ---
        .fail(xhr => showToast(xhr.responseJSON?.message || 'Un error ha ocorregut.', 'danger'));
    });

    // **MODIFICADO**: Respetar 'disabled'
    $(document).on('click', '.manage-btn', function(e) {
        e.preventDefault();
        if ($(this).is(':disabled') || $(this).hasClass('disabled')) return;

        itemToManage = {
            id: $(this).data('id'),
            name: $(this).data('name'),
            ownerId: $(this).data('owner-id')
        };
        $.getJSON('exercises.php', { ajax: true, action: 'check_exercise_usage', id: itemToManage.id })
        .done(response => {
            const modalTitle = $('#manageModalLabel');
            const modalBody = $('#manageModalBody').empty();
            const archiveBtn = $('#archiveBtn').off('click').hide();
            const deleteBtn = $('#deleteBtn').off('click').hide();

            // **MODIFICADO**: La lógica de permisos ahora es 'canManage' (Creator o Superadmin)
            const isCreator = itemToManage.ownerId == CURRENT_USER_ID;
            const canDelete = IS_SUPERADMIN || isCreator; // <- Esta es la lógica clave
            const isInUse = !response.is_usable_for_action;

            modalTitle.text(`Gestionar: ${itemToManage.name}`);

            if (isInUse) {
                let usageHtml = `<div class="alert alert-warning mb-3"><i class="bi bi-exclamation-triangle-fill me-2"></i><strong>Recurs en Ús</strong><br>Aquest exercici no es pot eliminar perquè s'està utilitzant en els següents plans:</div><ul class="list-group list-group-flush small">`;
                response.usage.forEach(item => { usageHtml += `<li class="list-group-item">${escapeHtml(item.name)}</li>`; });
                usageHtml += '</ul><hr>';
                modalBody.append(usageHtml);
            }

            // 'Arxivar' siempre está disponible para fisios
            archiveBtn.text('Arxivar').show().on('click', handlePersonalArchive);
            modalBody.append('<p>Pots arxivar aquest exercici per a ocultar-lo de les teues llistes.</p>');

            // 'Eliminar' solo está disponible si 'canDelete' es true
            if (canDelete) {
                if (IS_SUPERADMIN) {
                    modalBody.append('<hr><p>Com a administrador, pots eliminar aquest recurs permanentment.</p>');
                } else { // Es Creador
                    modalBody.append('<hr><p>Com a creador, pots eliminar aquest exercici permanentment.</p>');
                }

                if (isInUse) {
                    if (IS_SUPERADMIN) {
                        modalBody.append('<div class="alert alert-danger small"><strong>Atenció:</strong> Forçar l\'eliminació pot causar inconsistències en protocols o tractaments actius.</div>');
                        deleteBtn.text('Eliminar').show().on('click', handleDelete).prop('disabled', false);
                    } else { // Es Creador, pero está en uso
                        deleteBtn.prop('disabled', true).attr('title', 'No es pot eliminar perquè està en ús').show().text('Eliminar');
                    }
                } else {
                    // No está en uso y tiene permisos
                    deleteBtn.text('Eliminar Permanentment').show().on('click', handleDelete).prop('disabled', false);
                }
            }

            manageModal.show();
        });
    });

    function handlePersonalArchive() {
        $.post('exercises.php', { ajax: true, action: 'personal_archive', id: itemToManage.id }, 'json')
        .done(res => { showToast(res.message, 'success'); manageModal.hide(); fetchExercises(); })
        .fail(xhr => showToast(xhr.responseJSON.message, 'danger'));
    }

    // --- ★ TAREA 6 (Flash de Borrado) ---
    function handleDelete() {
            const promptName = String(itemToManage.name).replace(/'/g, ""); // Limpiar comillas simples
            if (prompt(`Per a confirmar l'eliminació permanent de "${promptName}", escriu ELIMINAR ací baix:`) === 'ELIMINAR') {

                const idToDelete = itemToManage.id;
                const $manageModal = (manageModal ? $(manageModal._element) : $('#manageModal'));

                // 1. Encontrar el elemento ANTES de borrarlo
                let elementToDelete;
                if (appState.viewMode === 'grid') {
                    // En grid, el data-id está en el manage button. Buscamos la .card padre.
                    elementToDelete = $(`.manage-btn[data-id="${idToDelete}"]`).closest('.card');
                } else {
                    // En lista, también está en el botón. Buscamos la tr padre.
                    elementToDelete = $(`tr .manage-btn[data-id="${idToDelete}"]`).closest('tr');
                }

                // 2. Ocultar el modal inmediatamente
                if(manageModal) manageModal.hide();

                if (elementToDelete.length > 0) {
                    // 3. Aplicar la animación de borrado (definida en style.css)
                    elementToDelete.addClass('flash-delete');

                    // 4. Esperar a que termine la animación (1.5s)
                    setTimeout(() => {
                        // 5. Enviar la petición de borrado SOLO DESPUÉS de la animación
                        $.post('exercises.php', { ajax: true, action: 'delete', id: idToDelete }, 'json')
                        .done(res => {
                            showToast(res.message, 'success');
                            // 6. Recargar la lista (el elemento ya está invisible)
                            fetchExercises();
                        })
                        .fail(xhr => {
                            showToast(xhr.responseJSON?.message || 'Error', 'danger');
                            // Si falla, quitamos la clase para que reaparezca
                            elementToDelete.removeClass('flash-delete');
                        });
                    }, 1500); // Debe coincidir con la duración de la animación CSS

                } else {
                    // Fallback (si no se encontró el elemento, solo borrar y recargar)
                    $.post('exercises.php', { ajax: true, action: 'delete', id: idToDelete }, 'json')
                    .done(res => { showToast(res.message, 'success'); fetchExercises(); })
                    .fail(xhr => showToast(xhr.responseJSON.message, 'danger'));
                }

            } else {
                showToast("L'acció d'eliminació ha sigut cancel·lada.", 'info');
            }
        }
    // --- ★ FIN TAREA 6 ---

    $(document).on('click', '.clone-btn', function(e) {
        e.preventDefault();
        const exerciseId = $(this).data('id');
        const exerciseTitle = $(this).data('title');
        $('#cloneExerciseForm input[name="original_exercise_id"]').val(exerciseId);
        $('#cloneExerciseForm input[name="title"]').val(`Còpia de: ${exerciseTitle}`);
        cloneExerciseModal.show();
    });

    // --- ★ TAREA 3 y 5 (Clonación Lógica y Flash Suave) ---
    $('#cloneExerciseForm').on('submit', function(e) {
        e.preventDefault();
        $.post('exercises.php', `ajax=true&action=clone_exercise&${$(this).serialize()}`, 'json')
        .done(response => {
            if (response.status === 'success') {
                showToast(response.message, 'success');
                cloneExerciseModal.hide();

                const idToHighlight = response.new_exercise_id; // <-- CAPTURE ID

                // No reseteamos la página, nos quedamos en la actual
                fetchExercises().done(() => {
                    if (idToHighlight) {
                        let elementToFlash;
                        if (appState.viewMode === 'grid') {
                            elementToFlash = $(`.manage-btn[data-id="${idToHighlight}"]`).closest('.card');
                        } else {
                            elementToFlash = $(`tr .manage-btn[data-id="${idToHighlight}"]`).closest('tr');
                        }

                        if (typeof flashElement === 'function' && elementToFlash && elementToFlash.length > 0) {
                            setTimeout(() => { // Delay para fluidez
                                flashElement(elementToFlash);
                            }, 50);
                        }
                    }
                });
            }
        })
        .fail(xhr => showToast(xhr.responseJSON?.message || 'Error desconegut.', 'danger'));
    });
    // --- ★ FIN TAREA 3 y 5 ---

    // ★★★ AÑADIR ESTE HANDLER ★★★
    $('#categoryFilter').on('change', function() {
        appState.categoryId = $(this).val();
        appState.page = 1;
        fetchExercises();
    });
    // ★★★ FIN ★★★

    setupSearch('#searchInput', '#clearSearchBtn', appState, fetchExercises);

    $('#filterMyExercises').on('change', function() { appState.filterMine = $(this).is(':checked'); appState.page = 1; fetchExercises(); });

    $('.sort-btn').on('click', function() {
        const newSort = $(this).data('sort');
        const newOrder = $(this).data('order') || (newSort === 'title' ? 'ASC' : 'DESC');

        if (appState.sort === newSort) {
            appState.order = appState.order === 'ASC' ? 'DESC' : 'ASC';
        } else {
            appState.sort = newSort;
            appState.order = newOrder;
        }
        $('.sort-btn').removeClass('active');
        $(this).addClass('active');
        appState.page = 1;
        fetchExercises();
    });

    $(document).on('click', '#exercise-library-container .sortable-header', function() {
        const newSort = $(this).data('sort');
        if (!newSort) return; // Evitar error
        const defaultOrder = (newSort === 'title' || newSort === 'category_name' || newSort === 'creator_surname') ? 'ASC' : 'DESC';

        if (appState.sort === newSort) {
            appState.order = appState.order === 'ASC' ? 'DESC' : 'ASC';
        } else {
            appState.sort = newSort;
            appState.order = defaultOrder;
        }

        appState.page = 1;
        fetchExercises();
    });


    $(document).on('click', '.page-link', function(e) { e.preventDefault(); appState.page = $(this).data('page'); fetchExercises(); });

    $('#filterMyMediaModal').on('change', updateMediaGrids);
    $('#mediaSearchInput').on('keyup', () => { let timeout; clearTimeout(timeout); timeout = setTimeout(updateMediaGrids, 300); });

    $(document).on('click', '.media-card', function() {
        const card = $(this);
        const mediaId = card.data('media-id');
        const isVideo = card.closest('#video-grid-container').length > 0;

        if (card.hasClass('selected')) {
            card.removeClass('selected');
            if (isVideo) $('#selectedVideoId').val(''); else $('#selectedImageId').val('');
        } else {
            $('.media-card').removeClass('selected');
            card.addClass('selected');
            if (isVideo) {
                $('#selectedVideoId').val(mediaId);
                $('#selectedImageId').val('');
            } else {
                $('#selectedImageId').val(mediaId);
                $('#selectedVideoId').val('');
            }
        }
        updateSelectedMediaDisplay();
    });

    // --- CARGA INICIAL ---
    if ($('#filterMyExercises').length > 0) { $('#filterMyExercises').prop('checked', appState.filterMine); }

    // --- ★ TAREA 2 (Limpieza UI) ---
    // Aplicar el estado inicial de los botones de vista/ordenación
    $('.toggle-view-btn').removeClass('active');
    if (appState.viewMode === 'grid') {
        $('#gridViewBtn').addClass('active');
        $('#sort-buttons-group').show();
    } else {
        $('#listViewBtn').addClass('active');
        $('#sort-buttons-group').hide();
    }
    // --- ★ FIN TAREA 2 ---

    fetchFormDependencies(); // Això crida fetchExercises() quan acaba
});
</script>

</body>
</html>
