Aller au contenu

Exercice : comptabilité personnelle multi-comptes

💰 Présentation

Application web complète de comptabilité personnelle : gestion multi-comptes bancaires, cartes bancaires, pointage des transactions et validation mensuelle — l'équivalent d'un classeur Excel avec plusieurs onglets, mais piloté par une base MariaDB.

Objectifs pédagogiques

  • SQL : relations entre tables (clés étrangères), jointures (INNER JOIN, LEFT JOIN), agrégations (SUM, COUNT, GROUP BY)
  • PHP : architecture simplifiée en pages séparées, sessions PHP, requêtes préparées PDO, traitement de formulaires
  • UX : navigation par onglets, feedback visuel (couleurs, badges), confirmation des actions critiques

📊 Les 5 onglets de l'application

Onglet Rôle
📊 Tableau de bord Vue d'ensemble de tous les comptes
🏦 Comptes bancaires Gestion des transactions avec pointage
💳 Cartes bancaires Suivi des dépenses par carte, résumés mensuels
✅ Validation mensuelle Transfert des dépenses carte → compte
🔄 Transactions récurrentes Revenus/dépenses réguliers

🗂️ Fichiers à créer

Fichier Rôle
config_v2.php Connexion PDO à la base de données
index_v2.php Page principale, routage entre les 5 onglets
database_v2.sql Script SQL de création des tables
pages/dashboard.php Tableau de bord
pages/comptes.php Gestion des comptes bancaires
pages/cartes.php Gestion des cartes bancaires
pages/validation.php Validation mensuelle
pages/recurrentes.php Transactions récurrentes

📦 Structure de la base de données

comptes                    → Comptes bancaires (Compte Courant, Livret A, etc.)
├── cartes                → Cartes bancaires liées aux comptes
├── transactions          → Transactions du compte (avec pointage)
└── transactions_cartes   → Transactions carte (en attente de validation)

categories                 → Catégories de revenus/dépenses
transactions_recurrentes   → Modèles de transactions régulières

Relations

  • Une carte appartient à un compte
  • Une transaction appartient à un compte
  • Une transaction carte appartient à une carte
  • Une fois validée, une transaction carte est liée à une transaction compte

⚙️ Prérequis

Environnement nécessaire

  • PHP 7.4+
  • MariaDB ou MySQL
  • Serveur web (Apache/Nginx) ou serveur PHP intégré

🚀 Installation pas à pas

1. Créer la base de données

mysql -u papinou -p < database_v2.sql

(ou coller le contenu de database_v2.sql dans phpMyAdmin, onglet SQL)

2. Configurer la connexion

Ajuster dans config_v2.php :

define('DB_USER', 'papinou');
define('DB_PASS', 'votre_mot_de_passe');

3. Organiser les fichiers

mkdir pages

Placer tous les fichiers *.php — sauf index_v2.php et config_v2.php — dans le dossier pages/.

4. Lancer l'application

php -S localhost:8080

Puis ouvrir http://localhost:8080/index_v2.php.

Application locale uniquement

Cet exercice tourne avec le serveur PHP intégré, en local — il n'est pas destiné à être déployé sur le site public.


💡 Guide d'utilisation

Le flux de travail

Dépense carte  →  Ajoutée avec un mois de validation (ex : Février)
Validation     →  En fin de mois, on valide
Compte         →  La transaction est ajoutée au compte
Pointage       →  On pointe avec le relevé bancaire

Pointage des transactions (comme dans Excel)

Dans un tableur, les transactions pointées sont marquées d'une étoile *. Ici, une case à cocher joue ce rôle dans l'onglet 🏦 Comptes bancaires : les lignes pointées apparaissent en vert.

Validation mensuelle des cartes (comme dans Excel)

Dans un tableur, on inscrit 1=janvier, 2=février… dans une colonne « validation mois ». Ici :

  1. Les dépenses carte sont ajoutées dans 💳 Cartes bancaires avec un mois de validation (1 à 12)
  2. En fin de mois, dans ✅ Validation mensuelle, un clic sur « Valider ce mois »
  3. Les transactions sont automatiquement transférées sur le compte

Résumés mensuels

Dans l'onglet 💳 Cartes bancaires, un tableau « Résumé mensuel des dépenses » indique, pour chaque mois, le nombre d'opérations, le total, la part validée et la part en attente.

Différences avec un tableur Excel

Excel Application web
Onglets en bas Navigation en haut
Pointage avec * Case à cocher
Validation mois avec 1, 2, 3… Bouton « Valider ce mois »
Résumés en haut de page Tableau dédié
Formules automatiques Calculs en temps réel
Un seul fichier Base de données

🔐 Sécurité

  • Anti-injection SQL : toutes les requêtes utilisent des requêtes préparées PDO (prepare() + execute())
  • Sessions PHP (session_start()) pour la navigation entre onglets
  • Identifiants de connexion en clair dans config_v2.php : acceptable en local pour l'exercice, jamais en production

📊 Quelques requêtes SQL utiles

Solde de tous les comptes :

SELECT
    c.nom,
    c.solde_initial +
    COALESCE(SUM(CASE WHEN t.type = 'revenu' THEN t.montant ELSE 0 END), 0) -
    COALESCE(SUM(CASE WHEN t.type = 'depense' THEN t.montant ELSE 0 END), 0) as solde_actuel
FROM comptes c
LEFT JOIN transactions t ON c.id = t.compte_id
GROUP BY c.id;

Transactions non pointées :

SELECT * FROM transactions
WHERE pointe = 0
ORDER BY date_transaction DESC;

Cartes à valider pour le mois en cours :

SELECT
    ca.nom as carte,
    COUNT(*) as nb,
    SUM(tc.montant) as total
FROM transactions_cartes tc
JOIN cartes ca ON tc.carte_id = ca.id
WHERE tc.validee = 0
    AND tc.mois_validation = MONTH(CURDATE())
    AND tc.annee_validation = YEAR(CURDATE())
GROUP BY ca.id;

🔧 Pistes d'extension

  • Génération automatique des transactions récurrentes
  • Graphiques de dépenses par catégorie
  • Export PDF/Excel
  • Import de fichiers bancaires (CSV, OFX)
  • Budgets mensuels par catégorie
  • Alertes de dépassement
  • Recherche et filtres avancés
  • (Plus avancé) Multi-utilisateurs avec authentification

🐛 Dépannage

Les transactions ne s'affichent pas

Vérifier qu'un compte ou une carte est bien sélectionné, et qu'il y a des données dans la base.

Le pointage ne fonctionne pas

Vérifier que JavaScript est activé et les permissions MySQL de l'utilisateur.

La validation mensuelle échoue

Vérifier que la carte est bien liée à un compte et que les contraintes de clés étrangères sont respectées.


💻 Code source complet

Copiez chacun des blocs ci-dessous dans un fichier du même nom, en respectant la structure de dossiers (pages/ pour les cinq derniers fichiers).

<?php
// Configuration de la base de données
define('DB_HOST', 'localhost');
define('DB_NAME', 'comptabilite_perso');
define('DB_USER', 'papinou');
define('DB_PASS', '');  // Remplacez par votre mot de passe

// Connexion à la base de données avec PDO
function getDB() {
    try {
        $dsn = "mysql:host=" . DB_HOST . ";dbname=" . DB_NAME . ";charset=utf8mb4";
        $options = [
            PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
            PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
            PDO::ATTR_EMULATE_PREPARES => false,
        ];

        return new PDO($dsn, DB_USER, DB_PASS, $options);
    } catch (PDOException $e) {
        die("Erreur de connexion : " . $e->getMessage());
    }
}

// Fonctions utilitaires
function formatMontant($montant) {
    return number_format($montant, 2, ',', ' ') . ' €';
}

function formatDate($date) {
    return date('d/m/Y', strtotime($date));
}

function getMoisNom($mois) {
    $moisNoms = [
        1 => 'Janvier', 2 => 'Février', 3 => 'Mars', 4 => 'Avril',
        5 => 'Mai', 6 => 'Juin', 7 => 'Juillet', 8 => 'Août',
        9 => 'Septembre', 10 => 'Octobre', 11 => 'Novembre', 12 => 'Décembre'
    ];
    return $moisNoms[$mois] ?? '';
}
?>
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
<?php
require_once 'config_v2.php';
session_start();

// Déterminer la page active
$page = $_GET['page'] ?? 'dashboard';

// Traitement des actions
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    $db = getDB();

    // Action selon le type de formulaire
    if (isset($_POST['action'])) {
        switch ($_POST['action']) {
            case 'ajouter_transaction':
                $stmt = $db->prepare("
                    INSERT INTO transactions (compte_id, libelle, montant, type, category_id, date_transaction, description, pointe) 
                    VALUES (?, ?, ?, ?, ?, ?, ?, 0)
                ");
                $stmt->execute([
                    $_POST['compte_id'],
                    $_POST['libelle'],
                    $_POST['montant'],
                    $_POST['type'],
                    $_POST['category_id'] ?: null,
                    $_POST['date_transaction'],
                    $_POST['description'] ?: null
                ]);
                break;

            case 'pointer_transaction':
                $stmt = $db->prepare("UPDATE transactions SET pointe = NOT pointe WHERE id = ?");
                $stmt->execute([$_POST['transaction_id']]);
                break;

            case 'ajouter_transaction_carte':
                $stmt = $db->prepare("
                    INSERT INTO transactions_cartes (carte_id, libelle, montant, category_id, date_transaction, description, mois_validation, annee_validation) 
                    VALUES (?, ?, ?, ?, ?, ?, ?, ?)
                ");
                $stmt->execute([
                    $_POST['carte_id'],
                    $_POST['libelle'],
                    $_POST['montant'],
                    $_POST['category_id'] ?: null,
                    $_POST['date_transaction'],
                    $_POST['description'] ?: null,
                    $_POST['mois_validation'],
                    $_POST['annee_validation']
                ]);
                break;

            case 'valider_transactions_carte':
                // Récupérer les transactions à valider
                $mois = $_POST['mois'];
                $annee = $_POST['annee'];
                $carte_id = $_POST['carte_id'];

                $stmt = $db->prepare("
                    SELECT * FROM transactions_cartes 
                    WHERE carte_id = ? AND mois_validation = ? AND annee_validation = ? AND validee = 0
                ");
                $stmt->execute([$carte_id, $mois, $annee]);
                $transactionsCartes = $stmt->fetchAll();

                // Récupérer le compte associé à la carte
                $stmt = $db->prepare("SELECT compte_id FROM cartes WHERE id = ?");
                $stmt->execute([$carte_id]);
                $compte_id = $stmt->fetchColumn();

                // Pour chaque transaction carte, créer une transaction compte
                foreach ($transactionsCartes as $tc) {
                    // Créer la transaction dans le compte
                    $stmt = $db->prepare("
                        INSERT INTO transactions (compte_id, libelle, montant, type, category_id, date_transaction, description, pointe) 
                        VALUES (?, ?, ?, 'depense', ?, ?, ?, 0)
                    ");
                    $stmt->execute([
                        $compte_id,
                        $tc['libelle'] . ' (Carte)',
                        $tc['montant'],
                        $tc['category_id'],
                        $tc['date_transaction'],
                        $tc['description']
                    ]);

                    $transaction_id = $db->lastInsertId();

                    // Marquer la transaction carte comme validée
                    $stmt = $db->prepare("UPDATE transactions_cartes SET validee = 1, transaction_compte_id = ? WHERE id = ?");
                    $stmt->execute([$transaction_id, $tc['id']]);
                }
                break;
        }

        header('Location: index_v2.php?page=' . $page);
        exit;
    }
}

// Suppression
if (isset($_GET['supprimer'])) {
    $db = getDB();
    $type = $_GET['type'] ?? 'transaction';

    if ($type === 'transaction') {
        $stmt = $db->prepare("DELETE FROM transactions WHERE id = ?");
        $stmt->execute([$_GET['supprimer']]);
    } elseif ($type === 'transaction_carte') {
        $stmt = $db->prepare("DELETE FROM transactions_cartes WHERE id = ?");
        $stmt->execute([$_GET['supprimer']]);
    }

    header('Location: index_v2.php?page=' . $page);
    exit;
}
?>
<!DOCTYPE html>
<html lang="fr">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Comptabilité Personnelle - Version Avancée</title>
    <style>
        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
        }

        body {
            font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, sans-serif;
            background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
            min-height: 100vh;
        }

        .header {
            background: white;
            box-shadow: 0 2px 10px rgba(0,0,0,0.1);
            padding: 0;
        }

        .header-content {
            max-width: 1400px;
            margin: 0 auto;
            padding: 20px;
        }

        h1 {
            color: #333;
            margin-bottom: 20px;
            font-size: 2em;
        }

        .tabs {
            display: flex;
            gap: 0;
            border-bottom: 2px solid #e0e0e0;
            overflow-x: auto;
        }

        .tab {
            padding: 15px 30px;
            background: transparent;
            border: none;
            cursor: pointer;
            font-size: 1em;
            font-weight: 500;
            color: #666;
            border-bottom: 3px solid transparent;
            transition: all 0.3s;
            white-space: nowrap;
            text-decoration: none;
            display: inline-block;
        }

        .tab:hover {
            background: #f8f9fa;
            color: #333;
        }

        .tab.active {
            color: #667eea;
            border-bottom-color: #667eea;
            background: #f8f9fa;
        }

        .container {
            max-width: 1400px;
            margin: 0 auto;
            padding: 30px 20px;
        }

        .card {
            background: white;
            padding: 30px;
            border-radius: 15px;
            box-shadow: 0 10px 30px rgba(0,0,0,0.2);
            margin-bottom: 30px;
        }

        h2 {
            color: #333;
            margin-bottom: 20px;
            padding-bottom: 10px;
            border-bottom: 3px solid #667eea;
            font-size: 1.5em;
        }

        .stats-grid {
            display: grid;
            grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
            gap: 20px;
            margin-bottom: 30px;
        }

        .stat-card {
            background: white;
            padding: 20px;
            border-radius: 10px;
            box-shadow: 0 5px 15px rgba(0,0,0,0.1);
            text-align: center;
        }

        .stat-label {
            color: #666;
            font-size: 0.85em;
            text-transform: uppercase;
            letter-spacing: 1px;
            margin-bottom: 8px;
        }

        .stat-value {
            font-size: 2em;
            font-weight: bold;
            margin-bottom: 5px;
        }

        .stat-value.positive { color: #28a745; }
        .stat-value.negative { color: #dc3545; }
        .stat-value.neutral { color: #667eea; }

        table {
            width: 100%;
            border-collapse: collapse;
            margin-top: 20px;
        }

        th {
            background: #f8f9fa;
            padding: 12px;
            text-align: left;
            font-weight: 600;
            color: #333;
            border-bottom: 2px solid #dee2e6;
            font-size: 0.9em;
        }

        td {
            padding: 12px;
            border-bottom: 1px solid #dee2e6;
        }

        tr:hover {
            background: #f8f9fa;
        }

        .form-group {
            margin-bottom: 20px;
        }

        label {
            display: block;
            color: #333;
            font-weight: 600;
            margin-bottom: 8px;
            font-size: 0.95em;
        }

        input, select, textarea {
            width: 100%;
            padding: 10px;
            border: 2px solid #e0e0e0;
            border-radius: 6px;
            font-size: 0.95em;
            transition: border-color 0.3s;
        }

        input:focus, select:focus, textarea:focus {
            outline: none;
            border-color: #667eea;
        }

        .form-row {
            display: grid;
            grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
            gap: 20px;
        }

        button, .btn {
            background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
            color: white;
            padding: 12px 25px;
            border: none;
            border-radius: 6px;
            font-size: 1em;
            font-weight: 600;
            cursor: pointer;
            transition: transform 0.2s, box-shadow 0.2s;
            display: inline-block;
            text-decoration: none;
            text-align: center;
        }

        button:hover, .btn:hover {
            transform: translateY(-2px);
            box-shadow: 0 5px 15px rgba(102, 126, 234, 0.4);
        }

        .btn-small {
            padding: 6px 12px;
            font-size: 0.85em;
        }

        .btn-danger {
            background: #dc3545;
        }

        .btn-danger:hover {
            box-shadow: 0 5px 15px rgba(220, 53, 69, 0.4);
        }

        .btn-success {
            background: #28a745;
        }

        .btn-success:hover {
            box-shadow: 0 5px 15px rgba(40, 167, 69, 0.4);
        }

        .badge {
            display: inline-block;
            padding: 4px 10px;
            border-radius: 12px;
            font-size: 0.8em;
            font-weight: 600;
            color: white;
        }

        .badge.revenu { background: #28a745; }
        .badge.depense { background: #dc3545; }

        .montant {
            font-weight: 600;
            font-size: 1.05em;
        }

        .montant.revenu { color: #28a745; }
        .montant.depense { color: #dc3545; }

        .checkbox-pointe {
            width: 20px;
            height: 20px;
            cursor: pointer;
        }

        .pointee {
            background: #d4edda !important;
        }

        .empty-state {
            text-align: center;
            padding: 40px;
            color: #999;
        }

        .compte-header {
            display: flex;
            align-items: center;
            gap: 15px;
            margin-bottom: 20px;
            padding: 15px;
            background: #f8f9fa;
            border-radius: 8px;
        }

        .compte-color {
            width: 40px;
            height: 40px;
            border-radius: 50%;
        }

        .compte-info h3 {
            margin: 0;
            color: #333;
        }

        .compte-info p {
            margin: 5px 0 0 0;
            color: #666;
            font-size: 0.9em;
        }

        @media (max-width: 768px) {
            .form-row {
                grid-template-columns: 1fr;
            }

            .stats-grid {
                grid-template-columns: 1fr;
            }

            table {
                font-size: 0.85em;
            }

            .tabs {
                flex-wrap: wrap;
            }
        }
    </style>
</head>
<body>
    <div class="header">
        <div class="header-content">
            <h1>💰 Comptabilité Personnelle</h1>
            <div class="tabs">
                <a href="?page=dashboard" class="tab <?= $page === 'dashboard' ? 'active' : '' ?>">📊 Tableau de bord</a>
                <a href="?page=comptes" class="tab <?= $page === 'comptes' ? 'active' : '' ?>">🏦 Comptes bancaires</a>
                <a href="?page=cartes" class="tab <?= $page === 'cartes' ? 'active' : '' ?>">💳 Cartes bancaires</a>
                <a href="?page=validation" class="tab <?= $page === 'validation' ? 'active' : '' ?>">✅ Validation mensuelle</a>
                <a href="?page=recurrentes" class="tab <?= $page === 'recurrentes' ? 'active' : '' ?>">🔄 Transactions récurrentes</a>
            </div>
        </div>
    </div>

    <div class="container">
        <?php
        // Inclure le contenu de la page selon l'onglet actif
        $pageFile = "pages/{$page}.php";
        if (file_exists($pageFile)) {
            include $pageFile;
        } else {
            echo "<div class='card'><p>Page non trouvée.</p></div>";
        }
        ?>
    </div>

    <script>
        // Fonction pour basculer le pointage
        function togglePointe(transactionId) {
            const form = document.createElement('form');
            form.method = 'POST';
            form.innerHTML = `
                <input type="hidden" name="action" value="pointer_transaction">
                <input type="hidden" name="transaction_id" value="${transactionId}">
            `;
            document.body.appendChild(form);
            form.submit();
        }
    </script>
</body>
</html>
-- Script d'initialisation de la base de données - VERSION AVANCÉE
-- À exécuter dans phpMyAdmin ou ligne de commande MySQL

CREATE DATABASE IF NOT EXISTS comptabilite_perso CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

USE comptabilite_perso;

-- Table des comptes bancaires
CREATE TABLE IF NOT EXISTS comptes (
    id INT AUTO_INCREMENT PRIMARY KEY,
    nom VARCHAR(100) NOT NULL,
    banque VARCHAR(100),
    numero_compte VARCHAR(50),
    solde_initial DECIMAL(10, 2) DEFAULT 0.00,
    couleur VARCHAR(7) DEFAULT '#667eea',
    actif BOOLEAN DEFAULT TRUE,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
) ENGINE=InnoDB;

-- Table des cartes bancaires
CREATE TABLE IF NOT EXISTS cartes (
    id INT AUTO_INCREMENT PRIMARY KEY,
    nom VARCHAR(100) NOT NULL,
    compte_id INT NOT NULL,
    numero_carte VARCHAR(20),
    couleur VARCHAR(7) DEFAULT '#764ba2',
    actif BOOLEAN DEFAULT TRUE,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    FOREIGN KEY (compte_id) REFERENCES comptes(id) ON DELETE CASCADE
) ENGINE=InnoDB;

-- Table des catégories
CREATE TABLE IF NOT EXISTS categories (
    id INT AUTO_INCREMENT PRIMARY KEY,
    nom VARCHAR(100) NOT NULL,
    type ENUM('revenu', 'depense') NOT NULL,
    couleur VARCHAR(7) DEFAULT '#6c757d',
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
) ENGINE=InnoDB;

-- Table des transactions (compte bancaire)
CREATE TABLE IF NOT EXISTS transactions (
    id INT AUTO_INCREMENT PRIMARY KEY,
    compte_id INT NOT NULL,
    libelle VARCHAR(255) NOT NULL,
    montant DECIMAL(10, 2) NOT NULL,
    type ENUM('revenu', 'depense') NOT NULL,
    category_id INT,
    date_transaction DATE NOT NULL,
    description TEXT,
    pointe BOOLEAN DEFAULT FALSE,
    recurrente BOOLEAN DEFAULT FALSE,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    FOREIGN KEY (compte_id) REFERENCES comptes(id) ON DELETE CASCADE,
    FOREIGN KEY (category_id) REFERENCES categories(id) ON DELETE SET NULL
) ENGINE=InnoDB;

-- Table des transactions cartes (en attente de validation)
CREATE TABLE IF NOT EXISTS transactions_cartes (
    id INT AUTO_INCREMENT PRIMARY KEY,
    carte_id INT NOT NULL,
    libelle VARCHAR(255) NOT NULL,
    montant DECIMAL(10, 2) NOT NULL,
    category_id INT,
    date_transaction DATE NOT NULL,
    description TEXT,
    mois_validation INT,
    annee_validation INT,
    validee BOOLEAN DEFAULT FALSE,
    transaction_compte_id INT,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    FOREIGN KEY (carte_id) REFERENCES cartes(id) ON DELETE CASCADE,
    FOREIGN KEY (category_id) REFERENCES categories(id) ON DELETE SET NULL,
    FOREIGN KEY (transaction_compte_id) REFERENCES transactions(id) ON DELETE SET NULL
) ENGINE=InnoDB;

-- Table des transactions récurrentes (modèles)
CREATE TABLE IF NOT EXISTS transactions_recurrentes (
    id INT AUTO_INCREMENT PRIMARY KEY,
    compte_id INT NOT NULL,
    libelle VARCHAR(255) NOT NULL,
    montant DECIMAL(10, 2) NOT NULL,
    type ENUM('revenu', 'depense') NOT NULL,
    category_id INT,
    jour_du_mois INT DEFAULT 1,
    description TEXT,
    actif BOOLEAN DEFAULT TRUE,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    FOREIGN KEY (compte_id) REFERENCES comptes(id) ON DELETE CASCADE,
    FOREIGN KEY (category_id) REFERENCES categories(id) ON DELETE SET NULL
) ENGINE=InnoDB;

-- Insertion de données de démonstration

-- Comptes bancaires
INSERT INTO comptes (nom, banque, numero_compte, solde_initial, couleur) VALUES
('Compte Courant', 'Crédit Agricole', 'FR76 XXXX XXXX XXXX XXXX', 1500.00, '#28a745'),
('Livret A', 'Crédit Agricole', 'FR76 YYYY YYYY YYYY YYYY', 5000.00, '#17a2b8'),
('Compte Épargne', 'LCL', 'FR76 ZZZZ ZZZZ ZZZZ ZZZZ', 2000.00, '#ffc107');

-- Cartes bancaires
INSERT INTO cartes (nom, compte_id, numero_carte, couleur) VALUES
('Carte Visa', 1, '**** **** **** 1234', '#dc3545'),
('Carte Mastercard', 1, '**** **** **** 5678', '#6f42c1');

-- Catégories
INSERT INTO categories (nom, type, couleur) VALUES
('Salaire', 'revenu', '#28a745'),
('Freelance', 'revenu', '#20c997'),
('Remboursement', 'revenu', '#17a2b8'),
('Autre revenu', 'revenu', '#6610f2'),
('Alimentation', 'depense', '#dc3545'),
('Logement', 'depense', '#fd7e14'),
('Transport', 'depense', '#ffc107'),
('Loisirs', 'depense', '#6f42c1'),
('Santé', 'depense', '#e83e8c'),
('Shopping', 'depense', '#6c757d'),
('Énergie', 'depense', '#fd7e14'),
('Téléphone/Internet', 'depense', '#20c997'),
('Assurances', 'depense', '#343a40'),
('Autre dépense', 'depense', '#6c757d');

-- Transactions récurrentes exemples
INSERT INTO transactions_recurrentes (compte_id, libelle, montant, type, category_id, jour_du_mois) VALUES
(1, 'Salaire mensuel', 2500.00, 'revenu', 1, 28),
(1, 'Loyer', 850.00, 'depense', 6, 5),
(1, 'EDF', 75.00, 'depense', 11, 15),
(1, 'Internet/Téléphone', 45.00, 'depense', 12, 10),
(1, 'Assurance habitation', 35.00, 'depense', 13, 20);
<?php
$db = getDB();

// Statistiques globales
$stmt = $db->query("
    SELECT 
        SUM(CASE WHEN t.type = 'revenu' THEN t.montant ELSE 0 END) as revenus,
        SUM(CASE WHEN t.type = 'depense' THEN t.montant ELSE 0 END) as depenses
    FROM transactions t
");
$stats = $stmt->fetch();

// Récupérer les soldes par compte
$stmt = $db->query("
    SELECT 
        c.id,
        c.nom,
        c.banque,
        c.couleur,
        c.solde_initial,
        COALESCE(SUM(CASE WHEN t.type = 'revenu' THEN t.montant ELSE 0 END), 0) as revenus,
        COALESCE(SUM(CASE WHEN t.type = 'depense' THEN t.montant ELSE 0 END), 0) as depenses
    FROM comptes c
    LEFT JOIN transactions t ON c.id = t.compte_id
    WHERE c.actif = 1
    GROUP BY c.id
    ORDER BY c.nom
");
$comptes = $stmt->fetchAll();

// Calcul du solde total
$soldeTotal = 0;
foreach ($comptes as &$compte) {
    $compte['solde_actuel'] = $compte['solde_initial'] + $compte['revenus'] - $compte['depenses'];
    $soldeTotal += $compte['solde_actuel'];
}

// Transactions carte non validées
$stmt = $db->query("
    SELECT COUNT(*) as nb, COALESCE(SUM(montant), 0) as total 
    FROM transactions_cartes 
    WHERE validee = 0
");
$cartesNonValidees = $stmt->fetch();

// Transactions non pointées
$stmt = $db->query("
    SELECT COUNT(*) as nb 
    FROM transactions 
    WHERE pointe = 0
");
$transactionsNonPointees = $stmt->fetch();
?>

<div class="stats-grid">
    <div class="stat-card">
        <div class="stat-label">Revenus totaux</div>
        <div class="stat-value positive">+<?= formatMontant($stats['revenus']) ?></div>
    </div>

    <div class="stat-card">
        <div class="stat-label">Dépenses totales</div>
        <div class="stat-value negative">-<?= formatMontant($stats['depenses']) ?></div>
    </div>

    <div class="stat-card">
        <div class="stat-label">Solde global</div>
        <div class="stat-value neutral"><?= formatMontant($soldeTotal) ?></div>
    </div>

    <div class="stat-card">
        <div class="stat-label">À pointer</div>
        <div class="stat-value" style="color: #ffc107;"><?= $transactionsNonPointees['nb'] ?></div>
        <small style="color: #666;">transaction(s)</small>
    </div>

    <div class="stat-card">
        <div class="stat-label">Cartes à valider</div>
        <div class="stat-value" style="color: #e83e8c;"><?= $cartesNonValidees['nb'] ?></div>
        <small style="color: #666;"><?= formatMontant($cartesNonValidees['total']) ?></small>
    </div>
</div>

<div class="card">
    <h2>💼 Vue par compte</h2>

    <?php if (empty($comptes)): ?>
        <div class="empty-state">
            <p>Aucun compte bancaire configuré.</p>
            <p>Ajoutez vos comptes dans la section "Comptes bancaires".</p>
        </div>
    <?php else: ?>
        <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: 20px;">
            <?php foreach ($comptes as $compte): ?>
                <div style="background: #f8f9fa; padding: 20px; border-radius: 10px; border-left: 5px solid <?= $compte['couleur'] ?>;">
                    <div style="display: flex; align-items: center; gap: 10px; margin-bottom: 15px;">
                        <div style="width: 15px; height: 15px; background: <?= $compte['couleur'] ?>; border-radius: 50%;"></div>
                        <h3 style="margin: 0; font-size: 1.1em;"><?= htmlspecialchars($compte['nom']) ?></h3>
                    </div>
                    <p style="color: #666; font-size: 0.9em; margin: 0 0 10px 0;">
                        <?= htmlspecialchars($compte['banque']) ?>
                    </p>
                    <div style="display: grid; grid-template-columns: 1fr 1fr; gap: 10px; margin-top: 15px; padding-top: 15px; border-top: 1px solid #dee2e6;">
                        <div>
                            <small style="color: #666;">Solde initial</small>
                            <div style="font-weight: 600;"><?= formatMontant($compte['solde_initial']) ?></div>
                        </div>
                        <div>
                            <small style="color: #666;">Solde actuel</small>
                            <div style="font-weight: 600; color: <?= $compte['solde_actuel'] >= 0 ? '#28a745' : '#dc3545' ?>;">
                                <?= formatMontant($compte['solde_actuel']) ?>
                            </div>
                        </div>
                    </div>
                    <div style="margin-top: 10px; font-size: 0.85em; color: #666;">
                        <div>Revenus: <span style="color: #28a745;">+<?= formatMontant($compte['revenus']) ?></span></div>
                        <div>Dépenses: <span style="color: #dc3545;">-<?= formatMontant($compte['depenses']) ?></span></div>
                    </div>
                </div>
            <?php endforeach; ?>
        </div>
    <?php endif; ?>
</div>

<?php
// Dernières transactions
$stmt = $db->prepare("
    SELECT t.*, c.nom as compte, c.couleur as compte_couleur, cat.nom as categorie, cat.couleur as cat_couleur
    FROM transactions t
    JOIN comptes c ON t.compte_id = c.id
    LEFT JOIN categories cat ON t.category_id = cat.id
    ORDER BY t.date_transaction DESC, t.created_at DESC
    LIMIT 10
");
$stmt->execute();
$dernieresTransactions = $stmt->fetchAll();
?>

<div class="card">
    <h2>📅 Dernières transactions</h2>

    <?php if (empty($dernieresTransactions)): ?>
        <div class="empty-state">
            <p>Aucune transaction enregistrée.</p>
        </div>
    <?php else: ?>
        <table>
            <thead>
                <tr>
                    <th>Date</th>
                    <th>Compte</th>
                    <th>Libellé</th>
                    <th>Catégorie</th>
                    <th>Montant</th>
                    <th>Pointé</th>
                </tr>
            </thead>
            <tbody>
                <?php foreach ($dernieresTransactions as $t): ?>
                    <tr class="<?= $t['pointe'] ? 'pointee' : '' ?>">
                        <td><?= formatDate($t['date_transaction']) ?></td>
                        <td>
                            <span style="display: inline-block; width: 10px; height: 10px; background: <?= $t['compte_couleur'] ?>; border-radius: 50%; margin-right: 5px;"></span>
                            <?= htmlspecialchars($t['compte']) ?>
                        </td>
                        <td>
                            <strong><?= htmlspecialchars($t['libelle']) ?></strong>
                            <?php if ($t['description']): ?>
                                <br><small style="color: #666;"><?= htmlspecialchars($t['description']) ?></small>
                            <?php endif; ?>
                        </td>
                        <td>
                            <?php if ($t['categorie']): ?>
                                <span style="display: inline-block; width: 10px; height: 10px; background: <?= $t['cat_couleur'] ?>; border-radius: 50%; margin-right: 5px;"></span>
                                <?= htmlspecialchars($t['categorie']) ?>
                            <?php else: ?>
                                <span style="color: #999;">-</span>
                            <?php endif; ?>
                        </td>
                        <td class="montant <?= $t['type'] ?>">
                            <?= $t['type'] === 'revenu' ? '+' : '-' ?>
                            <?= formatMontant($t['montant']) ?>
                        </td>
                        <td style="text-align: center;">
                            <?= $t['pointe'] ? '✓' : '—' ?>
                        </td>
                    </tr>
                <?php endforeach; ?>
            </tbody>
        </table>
    <?php endif; ?>
</div>
<?php
$db = getDB();

// Récupérer le compte sélectionné
$compte_id = $_GET['compte_id'] ?? null;

// Récupérer tous les comptes
$stmt = $db->query("SELECT * FROM comptes WHERE actif = 1 ORDER BY nom");
$comptes = $stmt->fetchAll();

// Si un compte est sélectionné, récupérer ses infos et transactions
$compteSelectionne = null;
$transactions = [];
$stats = ['revenus' => 0, 'depenses' => 0, 'solde_initial' => 0];

if ($compte_id) {
    $stmt = $db->prepare("SELECT * FROM comptes WHERE id = ?");
    $stmt->execute([$compte_id]);
    $compteSelectionne = $stmt->fetch();

    if ($compteSelectionne) {
        // Statistiques du compte
        $stmt = $db->prepare("
            SELECT 
                COALESCE(SUM(CASE WHEN type = 'revenu' THEN montant ELSE 0 END), 0) as revenus,
                COALESCE(SUM(CASE WHEN type = 'depense' THEN montant ELSE 0 END), 0) as depenses
            FROM transactions 
            WHERE compte_id = ?
        ");
        $stmt->execute([$compte_id]);
        $stats = $stmt->fetch();
        $stats['solde_initial'] = $compteSelectionne['solde_initial'];
        $stats['solde_actuel'] = $stats['solde_initial'] + $stats['revenus'] - $stats['depenses'];

        // Transactions non pointées
        $stmt = $db->prepare("SELECT COUNT(*) as nb FROM transactions WHERE compte_id = ? AND pointe = 0");
        $stmt->execute([$compte_id]);
        $stats['non_pointes'] = $stmt->fetchColumn();

        // Solde pointé
        $stmt = $db->prepare("
            SELECT 
                COALESCE(SUM(CASE WHEN type = 'revenu' THEN montant ELSE 0 END), 0) as revenus,
                COALESCE(SUM(CASE WHEN type = 'depense' THEN montant ELSE 0 END), 0) as depenses
            FROM transactions 
            WHERE compte_id = ? AND pointe = 1
        ");
        $stmt->execute([$compte_id]);
        $statsPointes = $stmt->fetch();
        $stats['solde_pointe'] = $stats['solde_initial'] + $statsPointes['revenus'] - $statsPointes['depenses'];

        // Récupérer les transactions
        $stmt = $db->prepare("
            SELECT t.*, c.nom as categorie, c.couleur as cat_couleur
            FROM transactions t
            LEFT JOIN categories c ON t.category_id = c.id
            WHERE t.compte_id = ?
            ORDER BY t.date_transaction DESC, t.created_at DESC
        ");
        $stmt->execute([$compte_id]);
        $transactions = $stmt->fetchAll();
    }
}

// Récupérer les catégories
$stmt = $db->query("SELECT * FROM categories ORDER BY type, nom");
$categories = $stmt->fetchAll();
?>

<div class="card">
    <h2>🏦 Sélectionner un compte</h2>
    <div style="display: grid; grid-template-columns: repeat(auto-fill, minmax(250px, 1fr)); gap: 15px;">
        <?php foreach ($comptes as $c): ?>
            <a href="?page=comptes&compte_id=<?= $c['id'] ?>" 
               style="text-decoration: none; color: inherit;">
                <div style="padding: 20px; background: <?= $compte_id == $c['id'] ? '#e7f1ff' : '#f8f9fa' ?>; 
                            border-radius: 10px; border-left: 5px solid <?= $c['couleur'] ?>; 
                            cursor: pointer; transition: all 0.3s;">
                    <div style="display: flex; align-items: center; gap: 10px;">
                        <div style="width: 12px; height: 12px; background: <?= $c['couleur'] ?>; border-radius: 50%;"></div>
                        <strong><?= htmlspecialchars($c['nom']) ?></strong>
                    </div>
                    <small style="color: #666;"><?= htmlspecialchars($c['banque']) ?></small>
                </div>
            </a>
        <?php endforeach; ?>
    </div>
</div>

<?php if ($compteSelectionne): ?>

<div class="compte-header">
    <div class="compte-color" style="background: <?= $compteSelectionne['couleur'] ?>;"></div>
    <div class="compte-info">
        <h3><?= htmlspecialchars($compteSelectionne['nom']) ?></h3>
        <p><?= htmlspecialchars($compteSelectionne['banque']) ?> - <?= htmlspecialchars($compteSelectionne['numero_compte']) ?></p>
    </div>
</div>

<div class="stats-grid" style="grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));">
    <div class="stat-card">
        <div class="stat-label">Solde initial</div>
        <div class="stat-value neutral"><?= formatMontant($stats['solde_initial']) ?></div>
    </div>

    <div class="stat-card">
        <div class="stat-label">Revenus</div>
        <div class="stat-value positive">+<?= formatMontant($stats['revenus']) ?></div>
    </div>

    <div class="stat-card">
        <div class="stat-label">Dépenses</div>
        <div class="stat-value negative">-<?= formatMontant($stats['depenses']) ?></div>
    </div>

    <div class="stat-card">
        <div class="stat-label">Solde actuel</div>
        <div class="stat-value <?= $stats['solde_actuel'] >= 0 ? 'positive' : 'negative' ?>">
            <?= formatMontant($stats['solde_actuel']) ?>
        </div>
    </div>

    <div class="stat-card">
        <div class="stat-label">Solde pointé</div>
        <div class="stat-value" style="color: #6610f2;"><?= formatMontant($stats['solde_pointe']) ?></div>
        <small style="color: #666;"><?= $stats['non_pointes'] ?> à pointer</small>
    </div>
</div>

<div class="card">
    <h2>➕ Ajouter une transaction</h2>
    <form method="POST">
        <input type="hidden" name="action" value="ajouter_transaction">
        <input type="hidden" name="compte_id" value="<?= $compte_id ?>">

        <div class="form-row">
            <div class="form-group">
                <label for="date_transaction">Date *</label>
                <input type="date" id="date_transaction" name="date_transaction" required value="<?= date('Y-m-d') ?>">
            </div>

            <div class="form-group">
                <label for="libelle">Libellé *</label>
                <input type="text" id="libelle" name="libelle" required placeholder="Ex: Courses Carrefour">
            </div>
        </div>

        <div class="form-row">
            <div class="form-group">
                <label for="type">Type *</label>
                <select id="type" name="type" required onchange="updateCategoriesCompte()">
                    <option value="">-- Choisir --</option>
                    <option value="revenu">Revenu</option>
                    <option value="depense">Dépense</option>
                </select>
            </div>

            <div class="form-group">
                <label for="montant">Montant (€) *</label>
                <input type="number" id="montant" name="montant" step="0.01" required placeholder="0.00">
            </div>
        </div>

        <div class="form-row">
            <div class="form-group">
                <label for="category_id">Catégorie</label>
                <select id="category_id" name="category_id">
                    <option value="">-- Aucune catégorie --</option>
                </select>
            </div>

            <div class="form-group">
                <label for="description">Description</label>
                <input type="text" id="description" name="description" placeholder="Détails optionnels">
            </div>
        </div>

        <button type="submit">Ajouter la transaction</button>
    </form>
</div>

<div class="card">
    <h2>📋 Historique des transactions</h2>
    <p style="color: #666; margin-bottom: 15px;">
        <strong>Pointage :</strong> Cliquez sur la case pour marquer une transaction comme pointée (★ = pointé)
    </p>

    <?php if (empty($transactions)): ?>
        <div class="empty-state">
            <p>Aucune transaction pour ce compte.</p>
        </div>
    <?php else: ?>
        <table>
            <thead>
                <tr>
                    <th style="width: 50px; text-align: center;">Pointé</th>
                    <th>Date</th>
                    <th>Libellé</th>
                    <th>Catégorie</th>
                    <th>Type</th>
                    <th>Montant</th>
                    <th>Actions</th>
                </tr>
            </thead>
            <tbody>
                <?php foreach ($transactions as $t): ?>
                    <tr class="<?= $t['pointe'] ? 'pointee' : '' ?>">
                        <td style="text-align: center;">
                            <input type="checkbox" 
                                   class="checkbox-pointe" 
                                   <?= $t['pointe'] ? 'checked' : '' ?>
                                   onchange="togglePointe(<?= $t['id'] ?>)"
                                   title="<?= $t['pointe'] ? 'Marquer comme non pointé' : 'Marquer comme pointé' ?>">
                        </td>
                        <td><?= formatDate($t['date_transaction']) ?></td>
                        <td>
                            <strong><?= htmlspecialchars($t['libelle']) ?></strong>
                            <?php if ($t['description']): ?>
                                <br><small style="color: #666;"><?= htmlspecialchars($t['description']) ?></small>
                            <?php endif; ?>
                        </td>
                        <td>
                            <?php if ($t['categorie']): ?>
                                <span style="display: inline-block; width: 10px; height: 10px; background: <?= $t['cat_couleur'] ?>; border-radius: 50%; margin-right: 5px;"></span>
                                <?= htmlspecialchars($t['categorie']) ?>
                            <?php else: ?>
                                <span style="color: #999;">-</span>
                            <?php endif; ?>
                        </td>
                        <td>
                            <span class="badge <?= $t['type'] ?>">
                                <?= $t['type'] === 'revenu' ? 'Revenu' : 'Dépense' ?>
                            </span>
                        </td>
                        <td class="montant <?= $t['type'] ?>">
                            <?= $t['type'] === 'revenu' ? '+' : '-' ?>
                            <?= formatMontant($t['montant']) ?>
                        </td>
                        <td>
                            <a href="?page=comptes&compte_id=<?= $compte_id ?>&supprimer=<?= $t['id'] ?>&type=transaction" 
                               class="btn btn-danger btn-small" 
                               onclick="return confirm('Supprimer cette transaction ?')">
                                Supprimer
                            </a>
                        </td>
                    </tr>
                <?php endforeach; ?>
            </tbody>
        </table>
    <?php endif; ?>
</div>

<script>
    const categoriesCompte = <?= json_encode($categories) ?>;

    function updateCategoriesCompte() {
        const typeSelect = document.getElementById('type');
        const categorySelect = document.getElementById('category_id');
        const selectedType = typeSelect.value;

        categorySelect.innerHTML = '<option value="">-- Aucune catégorie --</option>';

        if (selectedType) {
            const filtered = categoriesCompte.filter(cat => cat.type === selectedType);
            filtered.forEach(cat => {
                const option = document.createElement('option');
                option.value = cat.id;
                option.textContent = cat.nom;
                categorySelect.appendChild(option);
            });
        }
    }
</script>

<?php else: ?>
    <div class="card">
        <div class="empty-state">
            <p>Sélectionnez un compte ci-dessus pour voir ses transactions.</p>
        </div>
    </div>
<?php endif; ?>
<?php
$db = getDB();

// Récupérer la carte sélectionnée
$carte_id = $_GET['carte_id'] ?? null;

// Récupérer toutes les cartes
$stmt = $db->query("
    SELECT ca.*, co.nom as compte_nom, co.couleur as compte_couleur
    FROM cartes ca
    JOIN comptes co ON ca.compte_id = co.id
    WHERE ca.actif = 1
    ORDER BY ca.nom
");
$cartes = $stmt->fetchAll();

// Si une carte est sélectionnée
$carteSelectionnee = null;
$transactions = [];
$resumesMensuels = [];

if ($carte_id) {
    $stmt = $db->prepare("
        SELECT ca.*, co.nom as compte_nom
        FROM cartes ca
        JOIN comptes co ON ca.compte_id = co.id
        WHERE ca.id = ?
    ");
    $stmt->execute([$carte_id]);
    $carteSelectionnee = $stmt->fetch();

    if ($carteSelectionnee) {
        // Résumés mensuels (12 derniers mois)
        $stmt = $db->prepare("
            SELECT 
                mois_validation,
                annee_validation,
                COUNT(*) as nb_transactions,
                SUM(montant) as total,
                SUM(CASE WHEN validee = 1 THEN 1 ELSE 0 END) as nb_validees,
                SUM(CASE WHEN validee = 1 THEN montant ELSE 0 END) as total_validees
            FROM transactions_cartes
            WHERE carte_id = ?
            GROUP BY annee_validation, mois_validation
            ORDER BY annee_validation DESC, mois_validation DESC
            LIMIT 12
        ");
        $stmt->execute([$carte_id]);
        $resumesMensuels = $stmt->fetchAll();

        // Transactions
        $stmt = $db->prepare("
            SELECT t.*, c.nom as categorie, c.couleur as cat_couleur
            FROM transactions_cartes t
            LEFT JOIN categories c ON t.category_id = c.id
            WHERE t.carte_id = ?
            ORDER BY t.validee ASC, t.annee_validation DESC, t.mois_validation DESC, t.date_transaction DESC
        ");
        $stmt->execute([$carte_id]);
        $transactions = $stmt->fetchAll();
    }
}

// Récupérer les catégories de dépenses
$stmt = $db->query("SELECT * FROM categories WHERE type = 'depense' ORDER BY nom");
$categories = $stmt->fetchAll();

// Récupérer les comptes pour le formulaire
$stmt = $db->query("SELECT * FROM comptes WHERE actif = 1 ORDER BY nom");
$comptes = $stmt->fetchAll();
?>

<div class="card">
    <h2>💳 Sélectionner une carte</h2>
    <div style="display: grid; grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); gap: 15px;">
        <?php foreach ($cartes as $c): ?>
            <a href="?page=cartes&carte_id=<?= $c['id'] ?>" 
               style="text-decoration: none; color: inherit;">
                <div style="padding: 20px; background: <?= $carte_id == $c['id'] ? '#fff5f5' : '#f8f9fa' ?>; 
                            border-radius: 10px; border-left: 5px solid <?= $c['couleur'] ?>; 
                            cursor: pointer; transition: all 0.3s;">
                    <div style="display: flex; align-items: center; gap: 10px; margin-bottom: 5px;">
                        <div style="width: 12px; height: 12px; background: <?= $c['couleur'] ?>; border-radius: 50%;"></div>
                        <strong><?= htmlspecialchars($c['nom']) ?></strong>
                    </div>
                    <small style="color: #666;">
                        Compte: <?= htmlspecialchars($c['compte_nom']) ?><br>
                        <?= htmlspecialchars($c['numero_carte']) ?>
                    </small>
                </div>
            </a>
        <?php endforeach; ?>
    </div>
</div>

<?php if ($carteSelectionnee): ?>

<div class="compte-header" style="background: linear-gradient(135deg, <?= $carteSelectionnee['couleur'] ?>22 0%, <?= $carteSelectionnee['couleur'] ?>11 100%);">
    <div class="compte-color" style="background: <?= $carteSelectionnee['couleur'] ?>;"></div>
    <div class="compte-info">
        <h3><?= htmlspecialchars($carteSelectionnee['nom']) ?></h3>
        <p>Compte: <?= htmlspecialchars($carteSelectionnee['compte_nom']) ?> - <?= htmlspecialchars($carteSelectionnee['numero_carte']) ?></p>
    </div>
</div>

<?php if (!empty($resumesMensuels)): ?>
<div class="card">
    <h2>📊 Résumé mensuel des dépenses</h2>
    <div style="overflow-x: auto;">
        <table>
            <thead>
                <tr>
                    <th>Mois</th>
                    <th>Nombre d'opérations</th>
                    <th>Total</th>
                    <th>Validées</th>
                    <th>En attente</th>
                    <th>Statut</th>
                </tr>
            </thead>
            <tbody>
                <?php foreach ($resumesMensuels as $resume): ?>
                    <?php 
                    $enAttente = $resume['nb_transactions'] - $resume['nb_validees'];
                    $totalEnAttente = $resume['total'] - $resume['total_validees'];
                    ?>
                    <tr>
                        <td>
                            <strong><?= getMoisNom($resume['mois_validation']) ?> <?= $resume['annee_validation'] ?></strong>
                        </td>
                        <td><?= $resume['nb_transactions'] ?> opération(s)</td>
                        <td class="montant depense">
                            -<?= formatMontant($resume['total']) ?>
                        </td>
                        <td>
                            <?= $resume['nb_validees'] ?> (<?= formatMontant($resume['total_validees']) ?>)
                        </td>
                        <td style="color: <?= $enAttente > 0 ? '#e83e8c' : '#28a745' ?>;">
                            <?= $enAttente ?> (<?= formatMontant($totalEnAttente) ?>)
                        </td>
                        <td>
                            <?php if ($enAttente == 0): ?>
                                <span class="badge" style="background: #28a745;">✓ Validé</span>
                            <?php else: ?>
                                <span class="badge" style="background: #e83e8c;">En attente</span>
                            <?php endif; ?>
                        </td>
                    </tr>
                <?php endforeach; ?>
            </tbody>
        </table>
    </div>
</div>
<?php endif; ?>

<div class="card">
    <h2>➕ Ajouter une dépense carte</h2>
    <form method="POST">
        <input type="hidden" name="action" value="ajouter_transaction_carte">
        <input type="hidden" name="carte_id" value="<?= $carte_id ?>">

        <div class="form-row">
            <div class="form-group">
                <label for="date_transaction">Date de l'opération *</label>
                <input type="date" id="date_transaction" name="date_transaction" required value="<?= date('Y-m-d') ?>">
            </div>

            <div class="form-group">
                <label for="libelle">Libellé *</label>
                <input type="text" id="libelle" name="libelle" required placeholder="Ex: Restaurant">
            </div>
        </div>

        <div class="form-row">
            <div class="form-group">
                <label for="montant">Montant (€) *</label>
                <input type="number" id="montant" name="montant" step="0.01" required placeholder="0.00">
            </div>

            <div class="form-group">
                <label for="category_id">Catégorie</label>
                <select id="category_id" name="category_id">
                    <option value="">-- Aucune catégorie --</option>
                    <?php foreach ($categories as $cat): ?>
                        <option value="<?= $cat['id'] ?>"><?= htmlspecialchars($cat['nom']) ?></option>
                    <?php endforeach; ?>
                </select>
            </div>
        </div>

        <div class="form-row">
            <div class="form-group">
                <label for="mois_validation">Mois de validation *</label>
                <select id="mois_validation" name="mois_validation" required>
                    <?php for ($m = 1; $m <= 12; $m++): ?>
                        <option value="<?= $m ?>" <?= $m == date('n') ? 'selected' : '' ?>>
                            <?= $m ?> - <?= getMoisNom($m) ?>
                        </option>
                    <?php endfor; ?>
                </select>
            </div>

            <div class="form-group">
                <label for="annee_validation">Année de validation *</label>
                <select id="annee_validation" name="annee_validation" required>
                    <?php for ($a = date('Y') - 1; $a <= date('Y') + 1; $a++): ?>
                        <option value="<?= $a ?>" <?= $a == date('Y') ? 'selected' : '' ?>><?= $a ?></option>
                    <?php endfor; ?>
                </select>
            </div>
        </div>

        <div class="form-group">
            <label for="description">Description</label>
            <input type="text" id="description" name="description" placeholder="Détails optionnels">
        </div>

        <button type="submit">Ajouter la dépense</button>
    </form>
</div>

<div class="card">
    <h2>📋 Historique des dépenses carte</h2>
    <p style="color: #666; margin-bottom: 15px;">
        <strong>Note :</strong> Les dépenses en attente apparaissent en premier. Une fois validées, elles sont transférées sur le compte bancaire.
    </p>

    <?php if (empty($transactions)): ?>
        <div class="empty-state">
            <p>Aucune transaction pour cette carte.</p>
        </div>
    <?php else: ?>
        <table>
            <thead>
                <tr>
                    <th>Date</th>
                    <th>Libellé</th>
                    <th>Catégorie</th>
                    <th>Montant</th>
                    <th>Validation</th>
                    <th>Statut</th>
                    <th>Actions</th>
                </tr>
            </thead>
            <tbody>
                <?php foreach ($transactions as $t): ?>
                    <tr style="<?= !$t['validee'] ? 'background: #fff3cd;' : '' ?>">
                        <td><?= formatDate($t['date_transaction']) ?></td>
                        <td>
                            <strong><?= htmlspecialchars($t['libelle']) ?></strong>
                            <?php if ($t['description']): ?>
                                <br><small style="color: #666;"><?= htmlspecialchars($t['description']) ?></small>
                            <?php endif; ?>
                        </td>
                        <td>
                            <?php if ($t['categorie']): ?>
                                <span style="display: inline-block; width: 10px; height: 10px; background: <?= $t['cat_couleur'] ?>; border-radius: 50%; margin-right: 5px;"></span>
                                <?= htmlspecialchars($t['categorie']) ?>
                            <?php else: ?>
                                <span style="color: #999;">-</span>
                            <?php endif; ?>
                        </td>
                        <td class="montant depense">
                            -<?= formatMontant($t['montant']) ?>
                        </td>
                        <td>
                            <?= getMoisNom($t['mois_validation']) ?> <?= $t['annee_validation'] ?>
                        </td>
                        <td>
                            <?php if ($t['validee']): ?>
                                <span class="badge" style="background: #28a745;">✓ Validée</span>
                            <?php else: ?>
                                <span class="badge" style="background: #ffc107; color: #333;">En attente</span>
                            <?php endif; ?>
                        </td>
                        <td>
                            <?php if (!$t['validee']): ?>
                                <a href="?page=cartes&carte_id=<?= $carte_id ?>&supprimer=<?= $t['id'] ?>&type=transaction_carte" 
                                   class="btn btn-danger btn-small" 
                                   onclick="return confirm('Supprimer cette transaction ?')">
                                    Supprimer
                                </a>
                            <?php else: ?>
                                <span style="color: #999; font-size: 0.85em;">—</span>
                            <?php endif; ?>
                        </td>
                    </tr>
                <?php endforeach; ?>
            </tbody>
        </table>
    <?php endif; ?>
</div>

<?php else: ?>
    <div class="card">
        <div class="empty-state">
            <p>Sélectionnez une carte ci-dessus pour voir ses transactions.</p>
        </div>
    </div>
<?php endif; ?>
<?php
$db = getDB();

// Récupérer toutes les cartes avec leurs transactions non validées par mois
$stmt = $db->query("
    SELECT 
        c.id as carte_id,
        c.nom as carte_nom,
        c.couleur,
        co.nom as compte_nom,
        tc.mois_validation,
        tc.annee_validation,
        COUNT(*) as nb_transactions,
        SUM(tc.montant) as total
    FROM cartes c
    JOIN comptes co ON c.compte_id = co.id
    JOIN transactions_cartes tc ON c.id = tc.carte_id
    WHERE c.actif = 1 AND tc.validee = 0
    GROUP BY c.id, tc.annee_validation, tc.mois_validation
    ORDER BY tc.annee_validation DESC, tc.mois_validation DESC, c.nom
");
$validationsEnAttente = $stmt->fetchAll();

// Grouper par mois/année
$groupesValidation = [];
foreach ($validationsEnAttente as $v) {
    $key = $v['annee_validation'] . '-' . str_pad($v['mois_validation'], 2, '0', STR_PAD_LEFT);
    if (!isset($groupesValidation[$key])) {
        $groupesValidation[$key] = [
            'mois' => $v['mois_validation'],
            'annee' => $v['annee_validation'],
            'cartes' => []
        ];
    }
    $groupesValidation[$key]['cartes'][] = $v;
}
krsort($groupesValidation);
?>

<div class="card">
    <h2>✅ Validation mensuelle des cartes bancaires</h2>
    <p style="color: #666; margin-bottom: 20px;">
        Cette page vous permet de valider les dépenses carte et de les transférer sur vos comptes bancaires.<br>
        <strong>Important :</strong> La validation est irréversible. Les transactions validées apparaîtront dans le compte bancaire associé.
    </p>

    <?php if (empty($groupesValidation)): ?>
        <div class="empty-state">
            <p>🎉 Aucune transaction carte en attente de validation !</p>
            <p>Toutes vos dépenses ont été validées.</p>
        </div>
    <?php else: ?>
        <?php foreach ($groupesValidation as $key => $groupe): ?>
            <div style="background: #f8f9fa; padding: 20px; border-radius: 10px; margin-bottom: 20px;">
                <h3 style="margin: 0 0 15px 0; color: #333; font-size: 1.3em;">
                    📅 <?= getMoisNom($groupe['mois']) ?> <?= $groupe['annee'] ?>
                </h3>

                <div style="display: grid; gap: 15px;">
                    <?php 
                    $totalMois = 0;
                    foreach ($groupe['cartes'] as $carte): 
                        $totalMois += $carte['total'];
                    ?>
                        <div style="background: white; padding: 20px; border-radius: 8px; border-left: 5px solid <?= $carte['couleur'] ?>;">
                            <div style="display: flex; justify-content: space-between; align-items: center; flex-wrap: wrap; gap: 15px;">
                                <div style="flex: 1; min-width: 200px;">
                                    <div style="display: flex; align-items: center; gap: 10px; margin-bottom: 8px;">
                                        <div style="width: 15px; height: 15px; background: <?= $carte['couleur'] ?>; border-radius: 50%;"></div>
                                        <strong style="font-size: 1.1em;"><?= htmlspecialchars($carte['carte_nom']) ?></strong>
                                    </div>
                                    <p style="margin: 0; color: #666; font-size: 0.9em;">
                                        → Compte: <?= htmlspecialchars($carte['compte_nom']) ?>
                                    </p>
                                    <p style="margin: 5px 0 0 0; color: #666; font-size: 0.9em;">
                                        <?= $carte['nb_transactions'] ?> transaction(s)
                                    </p>
                                </div>

                                <div style="text-align: right;">
                                    <div class="montant depense" style="font-size: 1.5em; margin-bottom: 10px;">
                                        -<?= formatMontant($carte['total']) ?>
                                    </div>

                                    <form method="POST" style="display: inline;" 
                                          onsubmit="return confirm('Valider <?= $carte['nb_transactions'] ?> transaction(s) pour un total de <?= formatMontant($carte['total']) ?> ?\n\nCes transactions seront ajoutées au compte <?= htmlspecialchars($carte['compte_nom']) ?>.');">
                                        <input type="hidden" name="action" value="valider_transactions_carte">
                                        <input type="hidden" name="carte_id" value="<?= $carte['carte_id'] ?>">
                                        <input type="hidden" name="mois" value="<?= $carte['mois_validation'] ?>">
                                        <input type="hidden" name="annee" value="<?= $carte['annee_validation'] ?>">
                                        <button type="submit" class="btn btn-success btn-small">
                                            ✓ Valider ce mois
                                        </button>
                                    </form>

                                    <a href="?page=cartes&carte_id=<?= $carte['carte_id'] ?>" 
                                       class="btn btn-small" 
                                       style="background: #6c757d; margin-left: 5px;">
                                        Voir détails
                                    </a>
                                </div>
                            </div>
                        </div>
                    <?php endforeach; ?>
                </div>

                <div style="margin-top: 15px; padding-top: 15px; border-top: 2px solid #dee2e6; text-align: right;">
                    <strong style="font-size: 1.1em;">Total <?= getMoisNom($groupe['mois']) ?> :</strong>
                    <span class="montant depense" style="font-size: 1.3em; margin-left: 10px;">
                        -<?= formatMontant($totalMois) ?>
                    </span>
                </div>
            </div>
        <?php endforeach; ?>
    <?php endif; ?>
</div>

<?php
// Afficher les dernières validations
$stmt = $db->query("
    SELECT 
        c.nom as carte_nom,
        c.couleur,
        co.nom as compte_nom,
        tc.mois_validation,
        tc.annee_validation,
        COUNT(*) as nb_transactions,
        SUM(tc.montant) as total,
        MAX(tc.created_at) as date_validation
    FROM cartes c
    JOIN comptes co ON c.compte_id = co.id
    JOIN transactions_cartes tc ON c.id = tc.carte_id
    WHERE tc.validee = 1
    GROUP BY c.id, tc.annee_validation, tc.mois_validation
    ORDER BY date_validation DESC
    LIMIT 10
");
$dernieresValidations = $stmt->fetchAll();
?>

<?php if (!empty($dernieresValidations)): ?>
<div class="card">
    <h2>📜 Dernières validations</h2>
    <table>
        <thead>
            <tr>
                <th>Carte</th>
                <th>Compte</th>
                <th>Période validée</th>
                <th>Transactions</th>
                <th>Montant</th>
            </tr>
        </thead>
        <tbody>
            <?php foreach ($dernieresValidations as $v): ?>
                <tr>
                    <td>
                        <span style="display: inline-block; width: 10px; height: 10px; background: <?= $v['couleur'] ?>; border-radius: 50%; margin-right: 5px;"></span>
                        <?= htmlspecialchars($v['carte_nom']) ?>
                    </td>
                    <td><?= htmlspecialchars($v['compte_nom']) ?></td>
                    <td><?= getMoisNom($v['mois_validation']) ?> <?= $v['annee_validation'] ?></td>
                    <td><?= $v['nb_transactions'] ?> transaction(s)</td>
                    <td class="montant depense">-<?= formatMontant($v['total']) ?></td>
                </tr>
            <?php endforeach; ?>
        </tbody>
    </table>
</div>
<?php endif; ?>
<?php
$db = getDB();

// Récupérer toutes les transactions récurrentes
$stmt = $db->query("
    SELECT tr.*, c.nom as compte, c.couleur as compte_couleur, cat.nom as categorie, cat.couleur as cat_couleur
    FROM transactions_recurrentes tr
    JOIN comptes c ON tr.compte_id = c.id
    LEFT JOIN categories cat ON tr.category_id = cat.id
    WHERE tr.actif = 1
    ORDER BY tr.type, tr.libelle
");
$recurrentes = $stmt->fetchAll();

// Séparer par type
$revenus = array_filter($recurrentes, fn($t) => $t['type'] === 'revenu');
$depenses = array_filter($recurrentes, fn($t) => $t['type'] === 'depense');

// Récupérer les comptes et catégories pour les formulaires
$stmt = $db->query("SELECT * FROM comptes WHERE actif = 1 ORDER BY nom");
$comptes = $stmt->fetchAll();

$stmt = $db->query("SELECT * FROM categories ORDER BY type, nom");
$categories = $stmt->fetchAll();
?>

<div class="card">
    <h2>🔄 Transactions récurrentes</h2>
    <p style="color: #666; margin-bottom: 20px;">
        Les transactions récurrentes sont des modèles pour vos revenus et dépenses réguliers (salaire, loyer, abonnements, etc.).<br>
        <strong>Note :</strong> Cette version ne génère pas automatiquement les transactions. Vous pouvez les utiliser comme rappels.
    </p>
</div>

<div class="stats-grid" style="grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));">
    <div class="stat-card">
        <div class="stat-label">Revenus récurrents</div>
        <div class="stat-value positive">
            +<?= formatMontant(array_sum(array_column($revenus, 'montant'))) ?>
        </div>
        <small style="color: #666;"><?= count($revenus) ?> transaction(s)</small>
    </div>

    <div class="stat-card">
        <div class="stat-label">Dépenses récurrentes</div>
        <div class="stat-value negative">
            -<?= formatMontant(array_sum(array_column($depenses, 'montant'))) ?>
        </div>
        <small style="color: #666;"><?= count($depenses) ?> transaction(s)</small>
    </div>

    <div class="stat-card">
        <div class="stat-label">Solde récurrent</div>
        <div class="stat-value neutral">
            <?php 
            $soldeRecurrent = array_sum(array_column($revenus, 'montant')) - array_sum(array_column($depenses, 'montant'));
            echo formatMontant($soldeRecurrent);
            ?>
        </div>
    </div>
</div>

<?php if (!empty($revenus)): ?>
<div class="card">
    <h2 style="border-color: #28a745;">💰 Revenus récurrents</h2>
    <table>
        <thead>
            <tr>
                <th>Compte</th>
                <th>Libellé</th>
                <th>Catégorie</th>
                <th>Montant</th>
                <th>Jour du mois</th>
            </tr>
        </thead>
        <tbody>
            <?php foreach ($revenus as $t): ?>
                <tr>
                    <td>
                        <span style="display: inline-block; width: 10px; height: 10px; background: <?= $t['compte_couleur'] ?>; border-radius: 50%; margin-right: 5px;"></span>
                        <?= htmlspecialchars($t['compte']) ?>
                    </td>
                    <td>
                        <strong><?= htmlspecialchars($t['libelle']) ?></strong>
                        <?php if ($t['description']): ?>
                            <br><small style="color: #666;"><?= htmlspecialchars($t['description']) ?></small>
                        <?php endif; ?>
                    </td>
                    <td>
                        <?php if ($t['categorie']): ?>
                            <span style="display: inline-block; width: 10px; height: 10px; background: <?= $t['cat_couleur'] ?>; border-radius: 50%; margin-right: 5px;"></span>
                            <?= htmlspecialchars($t['categorie']) ?>
                        <?php else: ?>
                            <span style="color: #999;">-</span>
                        <?php endif; ?>
                    </td>
                    <td class="montant revenu">
                        +<?= formatMontant($t['montant']) ?>
                    </td>
                    <td style="text-align: center;">
                        Tous les <strong><?= $t['jour_du_mois'] ?></strong>
                    </td>
                </tr>
            <?php endforeach; ?>
        </tbody>
    </table>
</div>
<?php endif; ?>

<?php if (!empty($depenses)): ?>
<div class="card">
    <h2 style="border-color: #dc3545;">💸 Dépenses récurrentes</h2>
    <table>
        <thead>
            <tr>
                <th>Compte</th>
                <th>Libellé</th>
                <th>Catégorie</th>
                <th>Montant</th>
                <th>Jour du mois</th>
            </tr>
        </thead>
        <tbody>
            <?php foreach ($depenses as $t): ?>
                <tr>
                    <td>
                        <span style="display: inline-block; width: 10px; height: 10px; background: <?= $t['compte_couleur'] ?>; border-radius: 50%; margin-right: 5px;"></span>
                        <?= htmlspecialchars($t['compte']) ?>
                    </td>
                    <td>
                        <strong><?= htmlspecialchars($t['libelle']) ?></strong>
                        <?php if ($t['description']): ?>
                            <br><small style="color: #666;"><?= htmlspecialchars($t['description']) ?></small>
                        <?php endif; ?>
                    </td>
                    <td>
                        <?php if ($t['categorie']): ?>
                            <span style="display: inline-block; width: 10px; height: 10px; background: <?= $t['cat_couleur'] ?>; border-radius: 50%; margin-right: 5px;"></span>
                            <?= htmlspecialchars($t['categorie']) ?>
                        <?php else: ?>
                            <span style="color: #999;">-</span>
                        <?php endif; ?>
                    </td>
                    <td class="montant depense">
                        -<?= formatMontant($t['montant']) ?>
                    </td>
                    <td style="text-align: center;">
                        Tous les <strong><?= $t['jour_du_mois'] ?></strong>
                    </td>
                </tr>
            <?php endforeach; ?>
        </tbody>
    </table>
</div>
<?php endif; ?>

<?php if (empty($recurrentes)): ?>
<div class="card">
    <div class="empty-state">
        <p>Aucune transaction récurrente configurée.</p>
        <p>Les transactions récurrentes par défaut ont été ajoutées lors de l'installation de la base de données.</p>
    </div>
</div>
<?php endif; ?>

<div class="card" style="background: #f8f9fa; border: 2px dashed #dee2e6;">
    <h3 style="color: #666; margin-bottom: 10px;">💡 Fonctionnalité future</h3>
    <p style="color: #666; margin: 0;">
        Dans une version future, vous pourrez ajouter, modifier et supprimer des transactions récurrentes,
        et même les générer automatiquement chaque mois sur vos comptes bancaires.
    </p>
</div>