import React, { useState, useMemo } from "react";

const SCHEMA = {
  alerts: {
    group: "Notifications",
    description: "Alertes système générées pour les utilisateurs",
    columns: [
      { name: "id", type: "INTEGER", pk: true, fk: null, nullable: false, default: null },
      { name: "user_id", type: "INTEGER", pk: false, fk: "users.id", nullable: true, default: null },
      { name: "category", type: "VARCHAR(50)", pk: false, fk: null, nullable: false, default: null },
      { name: "level", type: "VARCHAR(20)", pk: false, fk: null, nullable: true, default: null },
      { name: "title", type: "VARCHAR(255)", pk: false, fk: null, nullable: true, default: null },
      { name: "message", type: "TEXT", pk: false, fk: null, nullable: false, default: null },
      { name: "source", type: "VARCHAR(50)", pk: false, fk: null, nullable: true, default: null },
      { name: "details", type: "JSON", pk: false, fk: null, nullable: true, default: null },
      { name: "read_at", type: "DATETIME", pk: false, fk: null, nullable: true, default: null },
      { name: "created_at", type: "DATETIME", pk: false, fk: null, nullable: false, default: "now()" },
    ]
  },
  app_settings: {
    group: "Système",
    description: "Paramètres globaux de l'application",
    columns: [
      { name: "key", type: "VARCHAR(100)", pk: true, fk: null, nullable: false, default: null },
      { name: "value", type: "TEXT", pk: false, fk: null, nullable: true, default: null },
      { name: "created_at", type: "DATETIME", pk: false, fk: null, nullable: false, default: "now()" },
      { name: "updated_at", type: "DATETIME", pk: false, fk: null, nullable: false, default: "now()" },
    ]
  },
  bootstrap_status: {
    group: "Hôtes",
    description: "État du bootstrapping Ansible par hôte",
    columns: [
      { name: "id", type: "INTEGER", pk: true, fk: null, nullable: false, default: null },
      { name: "host_id", type: "VARCHAR(50)", pk: false, fk: "hosts.id", nullable: false, default: null },
      { name: "status", type: "VARCHAR(50)", pk: false, fk: null, nullable: false, default: null },
      { name: "automation_user", type: "VARCHAR(50)", pk: false, fk: null, nullable: true, default: null },
      { name: "last_attempt", type: "DATETIME", pk: false, fk: null, nullable: true, default: null },
      { name: "error_message", type: "TEXT", pk: false, fk: null, nullable: true, default: null },
      { name: "created_at", type: "DATETIME", pk: false, fk: null, nullable: false, default: "now()" },
    ]
  },
  container_customizations: {
    group: "Docker",
    description: "Personnalisations visuelles de conteneurs par utilisateur",
    columns: [
      { name: "id", type: "INTEGER", pk: true, fk: null, nullable: false, default: null },
      { name: "user_id", type: "INTEGER", pk: false, fk: "users.id", nullable: true, default: null },
      { name: "host_id", type: "VARCHAR(50)", pk: false, fk: "hosts.id", nullable: false, default: null },
      { name: "container_id", type: "VARCHAR(64)", pk: false, fk: null, nullable: false, default: null },
      { name: "icon_key", type: "VARCHAR(100)", pk: false, fk: null, nullable: true, default: null },
      { name: "icon_color", type: "VARCHAR(20)", pk: false, fk: null, nullable: true, default: null },
      { name: "bg_color", type: "VARCHAR(20)", pk: false, fk: null, nullable: true, default: null },
      { name: "created_at", type: "DATETIME", pk: false, fk: null, nullable: false, default: "now()" },
      { name: "updated_at", type: "DATETIME", pk: false, fk: null, nullable: false, default: "now()" },
    ]
  },
  docker_alerts: {
    group: "Docker",
    description: "Alertes liées aux conteneurs Docker",
    columns: [
      { name: "id", type: "INTEGER", pk: true, fk: null, nullable: false, default: null },
      { name: "host_id", type: "VARCHAR(50)", pk: false, fk: "hosts.id", nullable: false, default: null },
      { name: "container_name", type: "VARCHAR(255)", pk: false, fk: null, nullable: false, default: null },
      { name: "severity", type: "VARCHAR(20)", pk: false, fk: null, nullable: false, default: "warning" },
      { name: "state", type: "VARCHAR(20)", pk: false, fk: null, nullable: false, default: "open" },
      { name: "message", type: "TEXT", pk: false, fk: null, nullable: true, default: null },
      { name: "opened_at", type: "DATETIME", pk: false, fk: null, nullable: false, default: "now()" },
      { name: "closed_at", type: "DATETIME", pk: false, fk: null, nullable: true, default: null },
      { name: "acknowledged_at", type: "DATETIME", pk: false, fk: null, nullable: true, default: null },
      { name: "acknowledged_by", type: "VARCHAR(100)", pk: false, fk: null, nullable: true, default: null },
      { name: "last_notified_at", type: "DATETIME", pk: false, fk: null, nullable: true, default: null },
    ]
  },
  docker_containers: {
    group: "Docker",
    description: "Inventaire des conteneurs Docker par hôte",
    columns: [
      { name: "id", type: "INTEGER", pk: true, fk: null, nullable: false, default: null },
      { name: "host_id", type: "VARCHAR(50)", pk: false, fk: "hosts.id", nullable: false, default: null },
      { name: "container_id", type: "VARCHAR(64)", pk: false, fk: null, nullable: false, default: null },
      { name: "name", type: "VARCHAR(255)", pk: false, fk: null, nullable: false, default: null },
      { name: "image", type: "VARCHAR(255)", pk: false, fk: null, nullable: true, default: null },
      { name: "state", type: "VARCHAR(20)", pk: false, fk: null, nullable: false, default: "unknown" },
      { name: "status", type: "VARCHAR(255)", pk: false, fk: null, nullable: true, default: null },
      { name: "health", type: "VARCHAR(20)", pk: false, fk: null, nullable: true, default: null },
      { name: "created_at", type: "DATETIME", pk: false, fk: null, nullable: true, default: null },
      { name: "ports", type: "JSON", pk: false, fk: null, nullable: true, default: null },
      { name: "labels", type: "JSON", pk: false, fk: null, nullable: true, default: null },
      { name: "compose_project", type: "VARCHAR(255)", pk: false, fk: null, nullable: true, default: null },
      { name: "last_update_at", type: "DATETIME", pk: false, fk: null, nullable: false, default: "now()" },
    ]
  },
  docker_images: {
    group: "Docker",
    description: "Images Docker disponibles sur les hôtes",
    columns: [
      { name: "id", type: "INTEGER", pk: true, fk: null, nullable: false, default: null },
      { name: "host_id", type: "VARCHAR(50)", pk: false, fk: "hosts.id", nullable: false, default: null },
      { name: "image_id", type: "VARCHAR(64)", pk: false, fk: null, nullable: false, default: null },
      { name: "repo_tags", type: "JSON", pk: false, fk: null, nullable: true, default: null },
      { name: "size", type: "BIGINT", pk: false, fk: null, nullable: true, default: null },
      { name: "created", type: "DATETIME", pk: false, fk: null, nullable: true, default: null },
      { name: "last_update_at", type: "DATETIME", pk: false, fk: null, nullable: false, default: "now()" },
    ]
  },
  docker_volumes: {
    group: "Docker",
    description: "Volumes Docker par hôte",
    columns: [
      { name: "id", type: "INTEGER", pk: true, fk: null, nullable: false, default: null },
      { name: "host_id", type: "VARCHAR(50)", pk: false, fk: "hosts.id", nullable: false, default: null },
      { name: "name", type: "VARCHAR(255)", pk: false, fk: null, nullable: false, default: null },
      { name: "driver", type: "VARCHAR(50)", pk: false, fk: null, nullable: true, default: null },
      { name: "mountpoint", type: "TEXT", pk: false, fk: null, nullable: true, default: null },
      { name: "scope", type: "VARCHAR(20)", pk: false, fk: null, nullable: true, default: null },
      { name: "last_update_at", type: "DATETIME", pk: false, fk: null, nullable: false, default: "now()" },
    ]
  },
  favorite_containers: {
    group: "Utilisateurs",
    description: "Conteneurs favoris par utilisateur et groupe",
    columns: [
      { name: "id", type: "INTEGER", pk: true, fk: null, nullable: false, default: null },
      { name: "user_id", type: "INTEGER", pk: false, fk: "users.id", nullable: true, default: null },
      { name: "docker_container_id", type: "INTEGER", pk: false, fk: "docker_containers.id", nullable: false, default: null },
      { name: "group_id", type: "INTEGER", pk: false, fk: "favorite_groups.id", nullable: true, default: null },
      { name: "created_at", type: "DATETIME", pk: false, fk: null, nullable: false, default: "now()" },
    ]
  },
  favorite_groups: {
    group: "Utilisateurs",
    description: "Groupes de favoris définis par l'utilisateur",
    columns: [
      { name: "id", type: "INTEGER", pk: true, fk: null, nullable: false, default: null },
      { name: "user_id", type: "INTEGER", pk: false, fk: "users.id", nullable: true, default: null },
      { name: "name", type: "VARCHAR(100)", pk: false, fk: null, nullable: false, default: null },
      { name: "sort_order", type: "INTEGER", pk: false, fk: null, nullable: false, default: "0" },
      { name: "color", type: "VARCHAR(20)", pk: false, fk: null, nullable: true, default: null },
      { name: "icon_key", type: "VARCHAR(100)", pk: false, fk: null, nullable: true, default: null },
      { name: "created_at", type: "DATETIME", pk: false, fk: null, nullable: false, default: "now()" },
      { name: "updated_at", type: "DATETIME", pk: false, fk: null, nullable: false, default: "now()" },
    ]
  },
  host_metrics: {
    group: "Hôtes",
    description: "Métriques système collectées par hôte (CPU, RAM, disque, réseau…)",
    columns: [
      { name: "id", type: "INTEGER", pk: true, fk: null, nullable: false, default: null },
      { name: "host_id", type: "VARCHAR(50)", pk: false, fk: "hosts.id", nullable: false, default: null },
      { name: "metric_type", type: "VARCHAR(50)", pk: false, fk: null, nullable: false, default: null },
      { name: "cpu_count", type: "INTEGER", pk: false, fk: null, nullable: true, default: null },
      { name: "cpu_model", type: "VARCHAR(200)", pk: false, fk: null, nullable: true, default: null },
      { name: "cpu_cores", type: "INTEGER", pk: false, fk: null, nullable: true, default: null },
      { name: "cpu_threads", type: "INTEGER", pk: false, fk: null, nullable: true, default: null },
      { name: "cpu_threads_per_core", type: "INTEGER", pk: false, fk: null, nullable: true, default: null },
      { name: "cpu_sockets", type: "INTEGER", pk: false, fk: null, nullable: true, default: null },
      { name: "cpu_mhz", type: "FLOAT", pk: false, fk: null, nullable: true, default: null },
      { name: "cpu_max_mhz", type: "FLOAT", pk: false, fk: null, nullable: true, default: null },
      { name: "cpu_min_mhz", type: "FLOAT", pk: false, fk: null, nullable: true, default: null },
      { name: "cpu_load_1m", type: "FLOAT", pk: false, fk: null, nullable: true, default: null },
      { name: "cpu_load_5m", type: "FLOAT", pk: false, fk: null, nullable: true, default: null },
      { name: "cpu_load_15m", type: "FLOAT", pk: false, fk: null, nullable: true, default: null },
      { name: "cpu_usage_percent", type: "FLOAT", pk: false, fk: null, nullable: true, default: null },
      { name: "cpu_temperature", type: "FLOAT", pk: false, fk: null, nullable: true, default: null },
      { name: "memory_total_mb", type: "INTEGER", pk: false, fk: null, nullable: true, default: null },
      { name: "memory_used_mb", type: "INTEGER", pk: false, fk: null, nullable: true, default: null },
      { name: "memory_free_mb", type: "INTEGER", pk: false, fk: null, nullable: true, default: null },
      { name: "memory_usage_percent", type: "FLOAT", pk: false, fk: null, nullable: true, default: null },
      { name: "swap_total_mb", type: "INTEGER", pk: false, fk: null, nullable: true, default: null },
      { name: "swap_used_mb", type: "INTEGER", pk: false, fk: null, nullable: true, default: null },
      { name: "swap_usage_percent", type: "FLOAT", pk: false, fk: null, nullable: true, default: null },
      { name: "disk_info", type: "JSON", pk: false, fk: null, nullable: true, default: null },
      { name: "disk_devices", type: "JSON", pk: false, fk: null, nullable: false, default: null },
      { name: "disk_root_total_gb", type: "FLOAT", pk: false, fk: null, nullable: true, default: null },
      { name: "disk_root_used_gb", type: "FLOAT", pk: false, fk: null, nullable: true, default: null },
      { name: "disk_root_usage_percent", type: "FLOAT", pk: false, fk: null, nullable: true, default: null },
      { name: "lvm_info", type: "JSON", pk: false, fk: null, nullable: true, default: null },
      { name: "zfs_info", type: "JSON", pk: false, fk: null, nullable: true, default: null },
      { name: "storage_details", type: "JSON", pk: false, fk: null, nullable: true, default: null },
      { name: "os_name", type: "VARCHAR(100)", pk: false, fk: null, nullable: true, default: null },
      { name: "os_version", type: "VARCHAR(100)", pk: false, fk: null, nullable: true, default: null },
      { name: "kernel_version", type: "VARCHAR(100)", pk: false, fk: null, nullable: true, default: null },
      { name: "hostname", type: "VARCHAR(200)", pk: false, fk: null, nullable: true, default: null },
      { name: "uptime_seconds", type: "INTEGER", pk: false, fk: null, nullable: true, default: null },
      { name: "uptime_human", type: "VARCHAR(100)", pk: false, fk: null, nullable: true, default: null },
      { name: "network_info", type: "JSON", pk: false, fk: null, nullable: true, default: null },
      { name: "raw_data", type: "JSON", pk: false, fk: null, nullable: true, default: null },
      { name: "collection_source", type: "VARCHAR(100)", pk: false, fk: null, nullable: true, default: null },
      { name: "collection_duration_ms", type: "INTEGER", pk: false, fk: null, nullable: true, default: null },
      { name: "error_message", type: "TEXT", pk: false, fk: null, nullable: true, default: null },
      { name: "collected_at", type: "DATETIME", pk: false, fk: null, nullable: false, default: "now()" },
      { name: "created_at", type: "DATETIME", pk: false, fk: null, nullable: false, default: "now()" },
    ]
  },
  hosts: {
    group: "Hôtes",
    description: "Inventaire des serveurs/hôtes gérés",
    columns: [
      { name: "id", type: "VARCHAR(50)", pk: true, fk: null, nullable: false, default: null },
      { name: "name", type: "VARCHAR(255)", pk: false, fk: null, nullable: false, default: null },
      { name: "ip_address", type: "VARCHAR(50)", pk: false, fk: null, nullable: false, default: null },
      { name: "status", type: "VARCHAR(50)", pk: false, fk: null, nullable: false, default: "'unknown'" },
      { name: "ansible_group", type: "VARCHAR(50)", pk: false, fk: null, nullable: true, default: null },
      { name: "last_seen", type: "DATETIME", pk: false, fk: null, nullable: true, default: null },
      { name: "reachable", type: "BOOLEAN", pk: false, fk: null, nullable: false, default: "0" },
      { name: "created_at", type: "DATETIME", pk: false, fk: null, nullable: false, default: "now()" },
      { name: "updated_at", type: "DATETIME", pk: false, fk: null, nullable: false, default: "now()" },
      { name: "deleted_at", type: "DATETIME", pk: false, fk: null, nullable: true, default: null },
      { name: "docker_enabled", type: "BOOLEAN", pk: false, fk: null, nullable: false, default: "0" },
      { name: "docker_version", type: "VARCHAR(50)", pk: false, fk: null, nullable: true, default: null },
      { name: "docker_status", type: "VARCHAR(20)", pk: false, fk: null, nullable: true, default: null },
      { name: "docker_last_collect_at", type: "DATETIME", pk: false, fk: null, nullable: true, default: null },
    ]
  },
  logs: {
    group: "Système",
    description: "Journal applicatif général",
    columns: [
      { name: "id", type: "INTEGER", pk: true, fk: null, nullable: false, default: null },
      { name: "level", type: "VARCHAR(50)", pk: false, fk: null, nullable: false, default: null },
      { name: "source", type: "VARCHAR(255)", pk: false, fk: null, nullable: true, default: null },
      { name: "message", type: "TEXT", pk: false, fk: null, nullable: false, default: null },
      { name: "details", type: "JSON", pk: false, fk: null, nullable: true, default: null },
      { name: "host_id", type: "VARCHAR(50)", pk: false, fk: null, nullable: true, default: null },
      { name: "task_id", type: "VARCHAR(50)", pk: false, fk: null, nullable: true, default: null },
      { name: "schedule_id", type: "VARCHAR(50)", pk: false, fk: null, nullable: true, default: null },
      { name: "created_at", type: "DATETIME", pk: false, fk: null, nullable: false, default: "now()" },
    ]
  },
  playbook_lint_results: {
    group: "Ansible",
    description: "Résultats d'analyse de qualité des playbooks Ansible",
    columns: [
      { name: "id", type: "INTEGER", pk: true, fk: null, nullable: false, default: null },
      { name: "filename", type: "VARCHAR(255)", pk: false, fk: null, nullable: false, default: null },
      { name: "quality_score", type: "INTEGER", pk: false, fk: null, nullable: false, default: "100" },
      { name: "total_issues", type: "INTEGER", pk: false, fk: null, nullable: false, default: "0" },
      { name: "errors_count", type: "INTEGER", pk: false, fk: null, nullable: false, default: "0" },
      { name: "warnings_count", type: "INTEGER", pk: false, fk: null, nullable: false, default: "0" },
      { name: "execution_time_ms", type: "INTEGER", pk: false, fk: null, nullable: false, default: "0" },
      { name: "issues_json", type: "TEXT", pk: false, fk: null, nullable: true, default: null },
      { name: "raw_output", type: "TEXT", pk: false, fk: null, nullable: true, default: null },
      { name: "created_at", type: "DATETIME", pk: false, fk: null, nullable: false, default: "auto" },
      { name: "updated_at", type: "DATETIME", pk: false, fk: null, nullable: false, default: "auto" },
    ]
  },
  schedule_runs: {
    group: "Ansible",
    description: "Historique des exécutions de planifications",
    columns: [
      { name: "id", type: "INTEGER", pk: true, fk: null, nullable: false, default: null },
      { name: "schedule_id", type: "VARCHAR(50)", pk: false, fk: "schedules.id", nullable: false, default: null },
      { name: "task_id", type: "VARCHAR(50)", pk: false, fk: "tasks.id", nullable: true, default: null },
      { name: "status", type: "VARCHAR(50)", pk: false, fk: null, nullable: false, default: null },
      { name: "started_at", type: "DATETIME", pk: false, fk: null, nullable: false, default: null },
      { name: "completed_at", type: "DATETIME", pk: false, fk: null, nullable: true, default: null },
      { name: "duration", type: "FLOAT", pk: false, fk: null, nullable: true, default: null },
      { name: "hosts_impacted", type: "INTEGER", pk: false, fk: null, nullable: true, default: "0" },
      { name: "error_message", type: "TEXT", pk: false, fk: null, nullable: true, default: null },
      { name: "output", type: "TEXT", pk: false, fk: null, nullable: true, default: null },
      { name: "created_at", type: "DATETIME", pk: false, fk: null, nullable: false, default: "now()" },
    ]
  },
  schedules: {
    group: "Ansible",
    description: "Planifications d'exécution de playbooks",
    columns: [
      { name: "id", type: "VARCHAR(50)", pk: true, fk: null, nullable: false, default: null },
      { name: "name", type: "VARCHAR(255)", pk: false, fk: null, nullable: false, default: null },
      { name: "description", type: "TEXT", pk: false, fk: null, nullable: true, default: null },
      { name: "playbook", type: "VARCHAR(255)", pk: false, fk: null, nullable: false, default: null },
      { name: "target_type", type: "VARCHAR(50)", pk: false, fk: null, nullable: true, default: "group" },
      { name: "target", type: "VARCHAR(255)", pk: false, fk: null, nullable: false, default: null },
      { name: "extra_vars", type: "JSON", pk: false, fk: null, nullable: true, default: null },
      { name: "schedule_type", type: "VARCHAR(50)", pk: false, fk: null, nullable: false, default: null },
      { name: "schedule_time", type: "DATETIME", pk: false, fk: null, nullable: true, default: null },
      { name: "recurrence_type", type: "VARCHAR(50)", pk: false, fk: null, nullable: true, default: null },
      { name: "recurrence_time", type: "VARCHAR(50)", pk: false, fk: null, nullable: true, default: null },
      { name: "recurrence_days", type: "TEXT", pk: false, fk: null, nullable: true, default: null },
      { name: "cron_expression", type: "VARCHAR(100)", pk: false, fk: null, nullable: true, default: null },
      { name: "timezone", type: "VARCHAR(100)", pk: false, fk: null, nullable: true, default: "America/Montreal" },
      { name: "start_at", type: "DATETIME", pk: false, fk: null, nullable: true, default: null },
      { name: "end_at", type: "DATETIME", pk: false, fk: null, nullable: true, default: null },
      { name: "enabled", type: "BOOLEAN", pk: false, fk: null, nullable: false, default: "True" },
      { name: "tags", type: "TEXT", pk: false, fk: null, nullable: true, default: null },
      { name: "next_run", type: "DATETIME", pk: false, fk: null, nullable: true, default: null },
      { name: "last_run", type: "DATETIME", pk: false, fk: null, nullable: true, default: null },
      { name: "last_status", type: "VARCHAR(50)", pk: false, fk: null, nullable: true, default: "never" },
      { name: "retry_on_failure", type: "INTEGER", pk: false, fk: null, nullable: true, default: "0" },
      { name: "timeout", type: "INTEGER", pk: false, fk: null, nullable: true, default: "3600" },
      { name: "notification_type", type: "VARCHAR(50)", pk: false, fk: null, nullable: true, default: "all" },
      { name: "run_count", type: "INTEGER", pk: false, fk: null, nullable: true, default: "0" },
      { name: "success_count", type: "INTEGER", pk: false, fk: null, nullable: true, default: "0" },
      { name: "failure_count", type: "INTEGER", pk: false, fk: null, nullable: true, default: "0" },
      { name: "created_at", type: "DATETIME", pk: false, fk: null, nullable: false, default: "now()" },
      { name: "updated_at", type: "DATETIME", pk: false, fk: null, nullable: false, default: "now()" },
      { name: "deleted_at", type: "DATETIME", pk: false, fk: null, nullable: true, default: null },
    ]
  },
  tasks: {
    group: "Ansible",
    description: "Tâches Ansible déclenchées manuellement ou via planification",
    columns: [
      { name: "id", type: "VARCHAR(50)", pk: true, fk: null, nullable: false, default: null },
      { name: "action", type: "VARCHAR(100)", pk: false, fk: null, nullable: false, default: null },
      { name: "target", type: "VARCHAR(255)", pk: false, fk: null, nullable: false, default: null },
      { name: "status", type: "VARCHAR(50)", pk: false, fk: null, nullable: false, default: "'pending'" },
      { name: "playbook", type: "VARCHAR(255)", pk: false, fk: null, nullable: true, default: null },
      { name: "started_at", type: "DATETIME", pk: false, fk: null, nullable: true, default: null },
      { name: "completed_at", type: "DATETIME", pk: false, fk: null, nullable: true, default: null },
      { name: "error_message", type: "TEXT", pk: false, fk: null, nullable: true, default: null },
      { name: "result_data", type: "JSON", pk: false, fk: null, nullable: true, default: null },
      { name: "created_at", type: "DATETIME", pk: false, fk: null, nullable: false, default: "now()" },
    ]
  },
  terminal_command_logs: {
    group: "Terminal",
    description: "Journal des commandes exécutées dans le terminal",
    columns: [
      { name: "id", type: "INTEGER", pk: true, fk: null, nullable: false, default: null },
      { name: "created_at", type: "DATETIME", pk: false, fk: null, nullable: false, default: "now()" },
      { name: "host_id", type: "VARCHAR(50)", pk: false, fk: "hosts.id", nullable: false, default: null },
      { name: "user_id", type: "INTEGER", pk: false, fk: "users.id", nullable: true, default: null },
      { name: "terminal_session_id", type: "VARCHAR(64)", pk: false, fk: null, nullable: true, default: null },
      { name: "command", type: "TEXT", pk: false, fk: null, nullable: false, default: null },
      { name: "command_hash", type: "VARCHAR(64)", pk: false, fk: null, nullable: false, default: null },
      { name: "source", type: "VARCHAR(20)", pk: false, fk: null, nullable: false, default: "'terminal'" },
      { name: "is_pinned", type: "BOOLEAN", pk: false, fk: null, nullable: false, default: "0" },
      { name: "is_blocked", type: "BOOLEAN", pk: false, fk: null, nullable: false, default: "0" },
      { name: "blocked_reason", type: "VARCHAR(255)", pk: false, fk: null, nullable: true, default: null },
      { name: "username", type: "VARCHAR(100)", pk: false, fk: null, nullable: true, default: null },
      { name: "host_name", type: "VARCHAR(100)", pk: false, fk: null, nullable: true, default: null },
    ]
  },
  terminal_sessions: {
    group: "Terminal",
    description: "Sessions de terminal actives ou fermées",
    columns: [
      { name: "id", type: "VARCHAR(50)", pk: true, fk: null, nullable: false, default: null },
      { name: "host_id", type: "VARCHAR(50)", pk: false, fk: null, nullable: false, default: null },
      { name: "host_name", type: "VARCHAR(255)", pk: false, fk: null, nullable: false, default: null },
      { name: "host_ip", type: "VARCHAR(50)", pk: false, fk: null, nullable: false, default: null },
      { name: "user_id", type: "INTEGER", pk: false, fk: null, nullable: true, default: null },
      { name: "username", type: "VARCHAR(50)", pk: false, fk: null, nullable: true, default: null },
      { name: "token_hash", type: "VARCHAR(128)", pk: false, fk: null, nullable: false, default: null },
      { name: "ttyd_port", type: "INTEGER", pk: false, fk: null, nullable: false, default: null },
      { name: "ttyd_pid", type: "INTEGER", pk: false, fk: null, nullable: true, default: null },
      { name: "mode", type: "VARCHAR(20)", pk: false, fk: null, nullable: false, default: "'embedded'" },
      { name: "status", type: "VARCHAR(20)", pk: false, fk: null, nullable: false, default: "'active'" },
      { name: "reason_closed", type: "VARCHAR(30)", pk: false, fk: null, nullable: true, default: null },
      { name: "created_at", type: "DATETIME", pk: false, fk: null, nullable: false, default: "now()" },
      { name: "last_seen_at", type: "DATETIME", pk: false, fk: null, nullable: false, default: "now()" },
      { name: "expires_at", type: "DATETIME", pk: false, fk: null, nullable: false, default: null },
      { name: "closed_at", type: "DATETIME", pk: false, fk: null, nullable: true, default: null },
    ]
  },
  users: {
    group: "Utilisateurs",
    description: "Comptes utilisateurs de l'application",
    columns: [
      { name: "id", type: "INTEGER", pk: true, fk: null, nullable: false, default: null },
      { name: "username", type: "VARCHAR(50)", pk: false, fk: null, nullable: false, default: null },
      { name: "email", type: "VARCHAR(255)", pk: false, fk: null, nullable: true, default: null },
      { name: "hashed_password", type: "VARCHAR(255)", pk: false, fk: null, nullable: false, default: null },
      { name: "role", type: "VARCHAR(20)", pk: false, fk: null, nullable: false, default: "'admin'" },
      { name: "is_active", type: "BOOLEAN", pk: false, fk: null, nullable: false, default: "1" },
      { name: "is_superuser", type: "BOOLEAN", pk: false, fk: null, nullable: false, default: "0" },
      { name: "display_name", type: "VARCHAR(100)", pk: false, fk: null, nullable: true, default: null },
      { name: "created_at", type: "DATETIME", pk: false, fk: null, nullable: false, default: "now()" },
      { name: "updated_at", type: "DATETIME", pk: false, fk: null, nullable: false, default: "now()" },
      { name: "last_login", type: "DATETIME", pk: false, fk: null, nullable: true, default: null },
      { name: "password_changed_at", type: "DATETIME", pk: false, fk: null, nullable: true, default: null },
      { name: "deleted_at", type: "DATETIME", pk: false, fk: null, nullable: true, default: null },
    ]
  },
};

const GROUP_COLORS = {
  "Hôtes": { bg: "#0f172a", accent: "#38bdf8", badge: "#0369a1", badgeText: "#e0f2fe" },
  "Docker": { bg: "#0a1628", accent: "#22d3ee", badge: "#0e7490", badgeText: "#cffafe" },
  "Ansible": { bg: "#1a0a2e", accent: "#a78bfa", badge: "#6d28d9", badgeText: "#ede9fe" },
  "Utilisateurs": { bg: "#0f1f0f", accent: "#4ade80", badge: "#15803d", badgeText: "#dcfce7" },
  "Terminal": { bg: "#1a1400", accent: "#fbbf24", badge: "#b45309", badgeText: "#fef3c7" },
  "Notifications": { bg: "#1a0a0a", accent: "#f87171", badge: "#b91c1c", badgeText: "#fee2e2" },
  "Système": { bg: "#111827", accent: "#94a3b8", badge: "#475569", badgeText: "#f1f5f9" },
};

const TYPE_COLOR = (t) => {
  if (t.startsWith("VARCHAR") || t === "TEXT") return "#7dd3fc";
  if (t === "INTEGER" || t === "BIGINT" || t === "FLOAT") return "#86efac";
  if (t === "DATETIME") return "#fcd34d";
  if (t === "BOOLEAN") return "#f9a8d4";
  if (t === "JSON") return "#c4b5fd";
  return "#e2e8f0";
};

const GROUPS = [...new Set(Object.values(SCHEMA).map(t => t.group))];

export default function App() {
  const [search, setSearch] = useState("");
  const [activeGroup, setActiveGroup] = useState("Tous");
  const [selectedTable, setSelectedTable] = useState(null);
  const [colSearch, setColSearch] = useState("");

  const tableNames = useMemo(() => Object.keys(SCHEMA).sort(), []);

  const filtered = useMemo(() => {
    return tableNames.filter(name => {
      const matchGroup = activeGroup === "Tous" || SCHEMA[name].group === activeGroup;
      const matchSearch = name.toLowerCase().includes(search.toLowerCase()) ||
        SCHEMA[name].description.toLowerCase().includes(search.toLowerCase());
      return matchGroup && matchSearch;
    });
  }, [tableNames, search, activeGroup]);

  const tableData = selectedTable ? SCHEMA[selectedTable] : null;
  const groupColor = tableData ? GROUP_COLORS[tableData.group] : null;

  const filteredCols = useMemo(() => {
    if (!tableData) return [];
    return tableData.columns.filter(c =>
      c.name.toLowerCase().includes(colSearch.toLowerCase()) ||
      c.type.toLowerCase().includes(colSearch.toLowerCase())
    );
  }, [tableData, colSearch]);

  const grouped = useMemo(() => {
    const g = {};
    GROUPS.forEach(grp => {
      const tables = filtered.filter(n => SCHEMA[n].group === grp);
      if (tables.length) g[grp] = tables;
    });
    return g;
  }, [filtered]);

  return (
    <div style={{ display: "flex", height: "100vh", background: "#0d1117", fontFamily: "'JetBrains Mono', 'Fira Code', monospace", color: "#c9d1d9", overflow: "hidden" }}>
      <style>{`
        @import url('https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@300;400;600;700&display=swap');
        ::-webkit-scrollbar { width: 6px; height: 6px; }
        ::-webkit-scrollbar-track { background: #161b22; }
        ::-webkit-scrollbar-thumb { background: #30363d; border-radius: 3px; }
        ::-webkit-scrollbar-thumb:hover { background: #484f58; }
        .table-item { transition: background 0.15s, border-color 0.15s; }
        .table-item:hover { background: #21262d !important; }
        .col-row:hover { background: #1c2128 !important; }
        .group-btn { transition: all 0.15s; }
        .group-btn:hover { filter: brightness(1.2); }
      `}</style>

      {/* SIDEBAR */}
      <div style={{ width: 280, background: "#161b22", borderRight: "1px solid #21262d", display: "flex", flexDirection: "column", flexShrink: 0 }}>
        {/* Header */}
        <div style={{ padding: "20px 16px 16px", borderBottom: "1px solid #21262d" }}>
          <div style={{ fontSize: 11, color: "#58a6ff", fontWeight: 700, letterSpacing: 3, marginBottom: 6, textTransform: "uppercase" }}>Schema Explorer</div>
          <div style={{ fontSize: 12, color: "#484f58" }}>{tableNames.length} tables · SQLAlchemy</div>
        </div>

        {/* Search */}
        <div style={{ padding: "12px 12px 8px" }}>
          <div style={{ position: "relative" }}>
            <span style={{ position: "absolute", left: 10, top: "50%", transform: "translateY(-50%)", color: "#484f58", fontSize: 13 }}>⌕</span>
            <input
              value={search}
              onChange={e => setSearch(e.target.value)}
              placeholder="Rechercher une table…"
              style={{ width: "100%", background: "#0d1117", border: "1px solid #30363d", borderRadius: 6, padding: "7px 10px 7px 30px", color: "#c9d1d9", fontSize: 12, outline: "none", boxSizing: "border-box" }}
            />
          </div>
        </div>

        {/* Groups filter */}
        <div style={{ padding: "0 12px 10px", display: "flex", flexWrap: "wrap", gap: 5 }}>
          {["Tous", ...GROUPS].map(g => {
            const isActive = activeGroup === g;
            const gc = GROUP_COLORS[g];
            return (
              <button key={g} className="group-btn" onClick={() => setActiveGroup(g)} style={{
                fontSize: 10, padding: "3px 8px", borderRadius: 4, cursor: "pointer", border: "none", fontFamily: "inherit", fontWeight: 600,
                background: isActive ? (gc ? gc.badge : "#21262d") : "#0d1117",
                color: isActive ? (gc ? gc.badgeText : "#c9d1d9") : "#58616a",
                letterSpacing: 0.5
              }}>
                {g}
              </button>
            );
          })}
        </div>

        {/* Table list */}
        <div style={{ flex: 1, overflowY: "auto", padding: "0 8px 16px" }}>
          {Object.keys(grouped).map(grp => {
            const gc = GROUP_COLORS[grp];
            return (
              <div key={grp} style={{ marginBottom: 8 }}>
                <div style={{ fontSize: 10, color: gc.accent, fontWeight: 700, letterSpacing: 2, textTransform: "uppercase", padding: "8px 8px 4px" }}>
                  {grp}
                </div>
                {grouped[grp].map(name => {
                  const isSelected = selectedTable === name;
                  return (
                    <div key={name} className="table-item" onClick={() => { setSelectedTable(name); setColSearch(""); }} style={{
                      padding: "8px 10px", borderRadius: 6, cursor: "pointer", marginBottom: 2,
                      background: isSelected ? "#1f2d3d" : "transparent",
                      border: isSelected ? `1px solid ${gc.accent}44` : "1px solid transparent",
                    }}>
                      <div style={{ display: "flex", alignItems: "center", gap: 7 }}>
                        <span style={{ color: isSelected ? gc.accent : "#484f58", fontSize: 12 }}>⬡</span>
                        <span style={{ fontSize: 12, color: isSelected ? "#e6edf3" : "#8b949e", fontWeight: isSelected ? 600 : 400 }}>{name}</span>
                        <span style={{ marginLeft: "auto", fontSize: 10, color: "#484f58" }}>{SCHEMA[name].columns.length}</span>
                      </div>
                    </div>
                  );
                })}
              </div>
            );
          })}
          {filtered.length === 0 && (
            <div style={{ padding: 20, color: "#484f58", fontSize: 12, textAlign: "center" }}>Aucune table trouvée</div>
          )}
        </div>
      </div>

      {/* MAIN CONTENT */}
      <div style={{ flex: 1, display: "flex", flexDirection: "column", overflow: "hidden" }}>
        {selectedTable && tableData ? (
          <>
            {/* Table header */}
            <div style={{ padding: "20px 28px 16px", borderBottom: "1px solid #21262d", background: "#161b22" }}>
              <div style={{ display: "flex", alignItems: "center", gap: 12, marginBottom: 6 }}>
                <span style={{ fontSize: 22, color: groupColor.accent }}>⬡</span>
                <h1 style={{ margin: 0, fontSize: 22, fontWeight: 700, color: "#e6edf3", letterSpacing: 1 }}>{selectedTable}</h1>
                <span style={{ fontSize: 11, padding: "2px 10px", borderRadius: 4, fontWeight: 700, background: groupColor.badge, color: groupColor.badgeText }}>
                  {tableData.group}
                </span>
              </div>
              <p style={{ margin: 0, fontSize: 13, color: "#8b949e" }}>{tableData.description}</p>

              {/* Stats row */}
              <div style={{ display: "flex", gap: 20, marginTop: 12 }}>
                {[
                  { label: "Colonnes", val: tableData.columns.length },
                  { label: "Clés primaires", val: tableData.columns.filter(c => c.pk).length },
                  { label: "Clés étrangères", val: tableData.columns.filter(c => c.fk).length },
                  { label: "Nullable", val: tableData.columns.filter(c => c.nullable).length },
                ].map(s => (
                  <div key={s.label} style={{ background: "#0d1117", border: "1px solid #21262d", borderRadius: 8, padding: "6px 14px", textAlign: "center" }}>
                    <div style={{ fontSize: 18, fontWeight: 700, color: groupColor.accent }}>{s.val}</div>
                    <div style={{ fontSize: 10, color: "#484f58", letterSpacing: 1 }}>{s.label}</div>
                  </div>
                ))}
              </div>
            </div>

            {/* Column search */}
            <div style={{ padding: "12px 28px 0", background: "#0d1117" }}>
              <div style={{ position: "relative", maxWidth: 340 }}>
                <span style={{ position: "absolute", left: 10, top: "50%", transform: "translateY(-50%)", color: "#484f58", fontSize: 13 }}>⌕</span>
                <input
                  value={colSearch}
                  onChange={e => setColSearch(e.target.value)}
                  placeholder="Filtrer les colonnes…"
                  style={{ width: "100%", background: "#161b22", border: "1px solid #30363d", borderRadius: 6, padding: "7px 10px 7px 30px", color: "#c9d1d9", fontSize: 12, outline: "none", boxSizing: "border-box" }}
                />
              </div>
            </div>

            {/* Columns table */}
            <div style={{ flex: 1, overflowY: "auto", padding: "12px 28px 28px", background: "#0d1117" }}>
              <table style={{ width: "100%", borderCollapse: "collapse", fontSize: 12 }}>
                <thead>
                  <tr style={{ borderBottom: "2px solid #21262d" }}>
                    {["Colonne", "Type", "Flags", "Défaut"].map(h => (
                      <th key={h} style={{ textAlign: "left", padding: "8px 12px", color: "#484f58", fontWeight: 700, fontSize: 10, letterSpacing: 2, textTransform: "uppercase" }}>{h}</th>
                    ))}
                  </tr>
                </thead>
                <tbody>
                  {filteredCols.map((col, i) => (
                    <tr key={col.name} className="col-row" style={{ borderBottom: "1px solid #161b22", background: i % 2 === 0 ? "transparent" : "#0a0f16" }}>
                      <td style={{ padding: "10px 12px", fontWeight: col.pk ? 700 : 400 }}>
                        <div style={{ display: "flex", alignItems: "center", gap: 7 }}>
                          {col.pk && <span title="Clé primaire" style={{ fontSize: 11, color: "#f59e0b" }}>🔑</span>}
                          {col.fk && !col.pk && <span title={`Clé étrangère → ${col.fk}`} style={{ fontSize: 11 }}>🔗</span>}
                          {!col.pk && !col.fk && <span style={{ fontSize: 11, color: "#30363d" }}>·</span>}
                          <span style={{ color: col.pk ? "#fbbf24" : col.fk ? "#60a5fa" : "#e6edf3" }}>{col.name}</span>
                        </div>
                        {col.fk && (
                          <div style={{ fontSize: 10, color: "#484f58", marginLeft: 22, marginTop: 2 }}>→ {col.fk}</div>
                        )}
                      </td>
                      <td style={{ padding: "10px 12px" }}>
                        <span style={{ color: TYPE_COLOR(col.type), fontWeight: 600 }}>{col.type}</span>
                      </td>
                      <td style={{ padding: "10px 12px" }}>
                        <div style={{ display: "flex", gap: 5, flexWrap: "wrap" }}>
                          {!col.nullable && (
                            <span style={{ fontSize: 10, padding: "1px 7px", borderRadius: 3, background: "#1c2e1c", color: "#4ade80", fontWeight: 600 }}>NOT NULL</span>
                          )}
                          {col.nullable && (
                            <span style={{ fontSize: 10, padding: "1px 7px", borderRadius: 3, background: "#1c1c1c", color: "#484f58" }}>NULL</span>
                          )}
                        </div>
                      </td>
                      <td style={{ padding: "10px 12px" }}>
                        {col.default ? (
                          <code style={{ fontSize: 11, color: "#c4b5fd", background: "#1e1a2e", padding: "2px 7px", borderRadius: 3 }}>{col.default}</code>
                        ) : (
                          <span style={{ color: "#30363d" }}>—</span>
                        )}
                      </td>
                    </tr>
                  ))}
                </tbody>
              </table>
              {filteredCols.length === 0 && (
                <div style={{ padding: 40, textAlign: "center", color: "#484f58", fontSize: 12 }}>Aucune colonne trouvée</div>
              )}
            </div>
          </>
        ) : (
          /* Welcome / overview */
          <div style={{ flex: 1, display: "flex", flexDirection: "column", alignItems: "center", justifyContent: "center", padding: 40, gap: 32 }}>
            <div style={{ textAlign: "center" }}>
              <div style={{ fontSize: 48, marginBottom: 12 }}>⬡</div>
              <h2 style={{ margin: 0, fontSize: 24, color: "#e6edf3", fontWeight: 700 }}>Modèle de Données</h2>
              <p style={{ color: "#484f58", fontSize: 13, marginTop: 8 }}>Sélectionnez une table dans le panneau de gauche</p>
            </div>
            <div style={{ display: "grid", gridTemplateColumns: "repeat(auto-fit, minmax(160px, 1fr))", gap: 12, maxWidth: 700, width: "100%" }}>
              {GROUPS.map(grp => {
                const gc = GROUP_COLORS[grp];
                const count = tableNames.filter(n => SCHEMA[n].group === grp).length;
                const firstTable = tableNames.find(n => SCHEMA[n].group === grp);
                return (
                  <div key={grp} onClick={() => { setActiveGroup(grp); setSelectedTable(firstTable); setColSearch(""); }} style={{
                    background: "#161b22", border: `1px solid ${gc.accent}33`, borderRadius: 10, padding: "16px 18px", cursor: "pointer",
                    transition: "all 0.15s"
                  }}
                    onMouseEnter={e => e.currentTarget.style.borderColor = gc.accent}
                    onMouseLeave={e => e.currentTarget.style.borderColor = gc.accent + "33"}
                  >
                    <div style={{ fontSize: 20, marginBottom: 8 }}>⬡</div>
                    <div style={{ fontSize: 13, fontWeight: 700, color: gc.accent, marginBottom: 4 }}>{grp}</div>
                    <div style={{ fontSize: 11, color: "#484f58" }}>{count} table{count > 1 ? "s" : ""}</div>
                  </div>
                );
              })}
            </div>
          </div>
        )}
      </div>
    </div>
  );
}
