/**
 * SQLite Database Wrapper for BraceFlow DEV
 * Mirrors the MySQL schema but uses SQLite for local development
 */
import Database from 'better-sqlite3';
import path from 'path';
import { fileURLToPath } from 'url';

const __dirname = path.dirname(fileURLToPath(import.meta.url));
// Use DB_PATH from env (Docker) or local path (dev)
const DB_PATH = process.env.DB_PATH || path.join(__dirname, '..', 'braceflow_DEV.db');

console.log(`Database path: ${DB_PATH}`);

// Initialize database
const db = new Database(DB_PATH);
db.pragma('journal_mode = WAL');

// Create tables
db.exec(`
  -- Patients table
  CREATE TABLE IF NOT EXISTS patients (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    mrn TEXT UNIQUE,
    first_name TEXT NOT NULL,
    last_name TEXT NOT NULL,
    date_of_birth TEXT,
    gender TEXT CHECK(gender IN ('male', 'female', 'other')),
    email TEXT,
    phone TEXT,
    address TEXT,
    diagnosis TEXT,
    curve_type TEXT,
    medical_history TEXT,
    referring_physician TEXT,
    insurance_info TEXT,
    notes TEXT,
    is_active INTEGER NOT NULL DEFAULT 1,
    created_by INTEGER,
    created_at TEXT NOT NULL DEFAULT (datetime('now')),
    updated_at TEXT NOT NULL DEFAULT (datetime('now')),
    FOREIGN KEY (created_by) REFERENCES users(id) ON DELETE SET NULL
  );

  -- Main cases table (linked to patients)
  CREATE TABLE IF NOT EXISTS brace_cases (
    case_id TEXT PRIMARY KEY,
    patient_id INTEGER,
    case_type TEXT NOT NULL DEFAULT 'braceflow',
    visit_date TEXT DEFAULT (date('now')),
    status TEXT NOT NULL DEFAULT 'created' CHECK(status IN (
      'created', 'running', 'completed', 'failed', 'cancelled',
      'processing_brace', 'brace_generated', 'brace_failed',
      'landmarks_detected', 'landmarks_approved', 'analysis_complete',
      'body_scan_uploaded'
    )),
    current_step TEXT DEFAULT NULL,
    execution_arn TEXT DEFAULT NULL,
    notes TEXT DEFAULT NULL,
    analysis_result TEXT DEFAULT NULL,
    landmarks_data TEXT DEFAULT NULL,
    analysis_data TEXT DEFAULT NULL,
    markers_data TEXT DEFAULT NULL,
    body_scan_path TEXT DEFAULT NULL,
    body_scan_url TEXT DEFAULT NULL,
    body_scan_metadata TEXT DEFAULT NULL,
    is_archived INTEGER NOT NULL DEFAULT 0,
    archived_at TEXT DEFAULT NULL,
    created_by INTEGER DEFAULT NULL,
    created_at TEXT NOT NULL DEFAULT (datetime('now')),
    updated_at TEXT NOT NULL DEFAULT (datetime('now')),
    FOREIGN KEY (patient_id) REFERENCES patients(id) ON DELETE SET NULL
  );

  -- Case steps table
  CREATE TABLE IF NOT EXISTS brace_case_steps (
    case_id TEXT NOT NULL,
    step_name TEXT NOT NULL,
    step_order INTEGER NOT NULL,
    status TEXT NOT NULL DEFAULT 'pending' CHECK(status IN (
      'pending', 'running', 'done', 'failed', 'waiting_for_landmarks'
    )),
    error_message TEXT DEFAULT NULL,
    started_at TEXT DEFAULT NULL,
    finished_at TEXT DEFAULT NULL,
    created_at TEXT NOT NULL DEFAULT (datetime('now')),
    updated_at TEXT NOT NULL DEFAULT (datetime('now')),
    PRIMARY KEY (case_id, step_name),
    FOREIGN KEY (case_id) REFERENCES brace_cases(case_id) ON DELETE CASCADE
  );

  -- Task tokens table (for pipeline state)
  CREATE TABLE IF NOT EXISTS brace_case_task_tokens (
    case_id TEXT NOT NULL,
    step_name TEXT NOT NULL,
    task_token TEXT NOT NULL,
    status TEXT NOT NULL DEFAULT 'active' CHECK(status IN ('active', 'consumed', 'expired')),
    created_at TEXT NOT NULL DEFAULT (datetime('now')),
    updated_at TEXT NOT NULL DEFAULT (datetime('now')),
    PRIMARY KEY (case_id, step_name),
    FOREIGN KEY (case_id) REFERENCES brace_cases(case_id) ON DELETE CASCADE
  );

  -- Users table (for authentication)
  CREATE TABLE IF NOT EXISTS users (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    username TEXT NOT NULL UNIQUE,
    password_hash TEXT NOT NULL,
    email TEXT DEFAULT NULL,
    full_name TEXT DEFAULT NULL,
    role TEXT NOT NULL DEFAULT 'user' CHECK(role IN ('admin', 'user', 'viewer')),
    is_active INTEGER NOT NULL DEFAULT 1,
    last_login TEXT DEFAULT NULL,
    created_at TEXT NOT NULL DEFAULT (datetime('now')),
    updated_at TEXT NOT NULL DEFAULT (datetime('now'))
  );

  -- User sessions table (for token management)
  CREATE TABLE IF NOT EXISTS user_sessions (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    user_id INTEGER NOT NULL,
    session_token TEXT NOT NULL UNIQUE,
    expires_at TEXT NOT NULL,
    created_at TEXT NOT NULL DEFAULT (datetime('now')),
    FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
  );

  -- Audit log table (for tracking admin actions)
  CREATE TABLE IF NOT EXISTS audit_log (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    user_id INTEGER DEFAULT NULL,
    action TEXT NOT NULL,
    entity_type TEXT NOT NULL,
    entity_id TEXT DEFAULT NULL,
    details TEXT DEFAULT NULL,
    ip_address TEXT DEFAULT NULL,
    created_at TEXT NOT NULL DEFAULT (datetime('now')),
    FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE SET NULL
  );

  -- API request logging table (for tracking all HTTP API calls)
  CREATE TABLE IF NOT EXISTS api_requests (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    user_id INTEGER DEFAULT NULL,
    username TEXT DEFAULT NULL,
    method TEXT NOT NULL,
    path TEXT NOT NULL,
    route_pattern TEXT DEFAULT NULL,
    query_params TEXT DEFAULT NULL,
    request_params TEXT DEFAULT NULL,
    file_uploads TEXT DEFAULT NULL,
    status_code INTEGER DEFAULT NULL,
    response_time_ms INTEGER DEFAULT NULL,
    response_summary TEXT DEFAULT NULL,
    ip_address TEXT DEFAULT NULL,
    user_agent TEXT DEFAULT NULL,
    request_body_size INTEGER DEFAULT NULL,
    response_body_size INTEGER DEFAULT NULL,
    error_message TEXT DEFAULT NULL,
    created_at TEXT NOT NULL DEFAULT (datetime('now')),
    FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE SET NULL
  );

  -- Create indexes
  CREATE INDEX IF NOT EXISTS idx_patients_name ON patients(last_name, first_name);
  CREATE INDEX IF NOT EXISTS idx_patients_mrn ON patients(mrn);
  CREATE INDEX IF NOT EXISTS idx_patients_created_by ON patients(created_by);
  CREATE INDEX IF NOT EXISTS idx_patients_active ON patients(is_active);
  CREATE INDEX IF NOT EXISTS idx_cases_patient ON brace_cases(patient_id);
  CREATE INDEX IF NOT EXISTS idx_cases_status ON brace_cases(status);
  CREATE INDEX IF NOT EXISTS idx_cases_created ON brace_cases(created_at);
  CREATE INDEX IF NOT EXISTS idx_steps_case_id ON brace_case_steps(case_id);
  CREATE INDEX IF NOT EXISTS idx_users_username ON users(username);
  CREATE INDEX IF NOT EXISTS idx_users_role ON users(role);
  CREATE INDEX IF NOT EXISTS idx_sessions_token ON user_sessions(session_token);
  CREATE INDEX IF NOT EXISTS idx_sessions_user ON user_sessions(user_id);
  CREATE INDEX IF NOT EXISTS idx_audit_user ON audit_log(user_id);
  CREATE INDEX IF NOT EXISTS idx_audit_action ON audit_log(action);
  CREATE INDEX IF NOT EXISTS idx_audit_created ON audit_log(created_at);
  CREATE INDEX IF NOT EXISTS idx_api_requests_user ON api_requests(user_id);
  CREATE INDEX IF NOT EXISTS idx_api_requests_path ON api_requests(path);
  CREATE INDEX IF NOT EXISTS idx_api_requests_method ON api_requests(method);
  CREATE INDEX IF NOT EXISTS idx_api_requests_status ON api_requests(status_code);
  CREATE INDEX IF NOT EXISTS idx_api_requests_created ON api_requests(created_at);
`);

// Migration: Add new columns to existing tables
try {
  db.exec(`ALTER TABLE brace_cases ADD COLUMN analysis_data TEXT DEFAULT NULL`);
} catch (e) { /* Column already exists */ }

try {
  db.exec(`ALTER TABLE brace_cases ADD COLUMN body_scan_path TEXT DEFAULT NULL`);
} catch (e) { /* Column already exists */ }

try {
  db.exec(`ALTER TABLE brace_cases ADD COLUMN body_scan_url TEXT DEFAULT NULL`);
} catch (e) { /* Column already exists */ }

try {
  db.exec(`ALTER TABLE brace_cases ADD COLUMN body_scan_metadata TEXT DEFAULT NULL`);
} catch (e) { /* Column already exists */ }

try {
  db.exec(`ALTER TABLE brace_cases ADD COLUMN created_by INTEGER DEFAULT NULL`);
} catch (e) { /* Column already exists */ }

// Migration: Add new columns to api_requests table for enhanced logging
try {
  db.exec(`ALTER TABLE api_requests ADD COLUMN route_pattern TEXT DEFAULT NULL`);
} catch (e) { /* Column already exists */ }

try {
  db.exec(`ALTER TABLE api_requests ADD COLUMN request_params TEXT DEFAULT NULL`);
} catch (e) { /* Column already exists */ }

try {
  db.exec(`ALTER TABLE api_requests ADD COLUMN file_uploads TEXT DEFAULT NULL`);
} catch (e) { /* Column already exists */ }

try {
  db.exec(`ALTER TABLE api_requests ADD COLUMN response_summary TEXT DEFAULT NULL`);
} catch (e) { /* Column already exists */ }

// Migration: Add patient_id to brace_cases
try {
  db.exec(`ALTER TABLE brace_cases ADD COLUMN patient_id INTEGER DEFAULT NULL`);
} catch (e) { /* Column already exists */ }

// Migration: Add visit_date to brace_cases
try {
  db.exec(`ALTER TABLE brace_cases ADD COLUMN visit_date TEXT DEFAULT NULL`);
} catch (e) { /* Column already exists */ }

// Migration: Add is_archived to brace_cases
try {
  db.exec(`ALTER TABLE brace_cases ADD COLUMN is_archived INTEGER NOT NULL DEFAULT 0`);
} catch (e) { /* Column already exists */ }

try {
  db.exec(`ALTER TABLE brace_cases ADD COLUMN archived_at TEXT DEFAULT NULL`);
} catch (e) { /* Column already exists */ }

// Insert default admin user if not exists (password: admin123)
// Note: In production, use proper bcrypt hashing. This is a simple hash for dev.
try {
  const existingAdmin = db.prepare(`SELECT id FROM users WHERE username = ?`).get('admin');
  if (!existingAdmin) {
    // Simple hash for dev - in production use bcrypt
    db.prepare(`
      INSERT INTO users (username, password_hash, full_name, role, is_active)
      VALUES (?, ?, ?, ?, ?)
    `).run('admin', 'admin123', 'Administrator', 'admin', 1);
    console.log('Created default admin user (admin/admin123)');
  }
} catch (e) { /* User already exists or table not ready */ }

// Step names for the pipeline
const STEP_NAMES = [
  'LandmarkDetection',
  'LandmarkApproval',
  'SpineAnalysis',
  'BodyScanUpload',
  'BraceGeneration',
  'BraceApproval'
];

/**
 * Create a new case (optionally linked to a patient)
 */
export function createCase(caseId, caseType = 'braceflow', notes = null, patientId = null, visitDate = null) {
  const insertCase = db.prepare(`
    INSERT INTO brace_cases (case_id, patient_id, case_type, visit_date, status, notes, created_at, updated_at)
    VALUES (?, ?, ?, ?, 'created', ?, datetime('now'), datetime('now'))
  `);

  const insertStep = db.prepare(`
    INSERT INTO brace_case_steps (case_id, step_name, step_order, status, created_at, updated_at)
    VALUES (?, ?, ?, 'pending', datetime('now'), datetime('now'))
  `);

  const transaction = db.transaction(() => {
    insertCase.run(caseId, patientId, caseType, visitDate || new Date().toISOString().split('T')[0], notes);
    STEP_NAMES.forEach((stepName, idx) => {
      insertStep.run(caseId, stepName, idx + 1);
    });
  });

  transaction();
  return { caseId, patientId, status: 'created', steps: STEP_NAMES };
}

/**
 * List all cases with patient info
 * @param {Object} options - Query options
 * @param {boolean} options.includeArchived - Include archived cases (for admin view)
 * @param {boolean} options.archivedOnly - Only show archived cases
 */
export function listCases(options = {}) {
  const { includeArchived = false, archivedOnly = false } = options;
  
  let whereClause = '';
  if (archivedOnly) {
    whereClause = 'WHERE c.is_archived = 1';
  } else if (!includeArchived) {
    whereClause = 'WHERE c.is_archived = 0';
  }
  
  const stmt = db.prepare(`
    SELECT c.case_id as caseId, c.patient_id, c.case_type, c.visit_date, c.status, c.current_step, c.notes, 
           c.analysis_result, c.landmarks_data, c.is_archived, c.archived_at, c.created_at, c.updated_at,
           p.first_name as patient_first_name, p.last_name as patient_last_name,
           p.mrn as patient_mrn
    FROM brace_cases c
    LEFT JOIN patients p ON c.patient_id = p.id
    ${whereClause}
    ORDER BY c.created_at DESC
  `);
  
  const rows = stmt.all();
  
  // Transform to include patient object
  return rows.map(row => ({
    caseId: row.caseId,
    patient_id: row.patient_id,
    patient: row.patient_id ? {
      id: row.patient_id,
      firstName: row.patient_first_name,
      lastName: row.patient_last_name,
      fullName: `${row.patient_first_name} ${row.patient_last_name}`,
      mrn: row.patient_mrn
    } : null,
    case_type: row.case_type,
    visit_date: row.visit_date,
    status: row.status,
    current_step: row.current_step,
    notes: row.notes,
    analysis_result: row.analysis_result,
    landmarks_data: row.landmarks_data,
    is_archived: row.is_archived === 1,
    archived_at: row.archived_at,
    created_at: row.created_at,
    updated_at: row.updated_at
  }));
}

/**
 * Archive a case (soft delete)
 */
export function archiveCase(caseId) {
  const stmt = db.prepare(`
    UPDATE brace_cases 
    SET is_archived = 1, archived_at = datetime('now'), updated_at = datetime('now')
    WHERE case_id = ?
  `);
  return stmt.run(caseId);
}

/**
 * Unarchive a case
 */
export function unarchiveCase(caseId) {
  const stmt = db.prepare(`
    UPDATE brace_cases 
    SET is_archived = 0, archived_at = NULL, updated_at = datetime('now')
    WHERE case_id = ?
  `);
  return stmt.run(caseId);
}

/**
 * Get case by ID with steps and patient info
 */
export function getCase(caseId) {
  const caseStmt = db.prepare(`
    SELECT c.case_id, c.patient_id, c.case_type, c.visit_date, c.status, c.current_step, c.notes, 
           c.analysis_result, c.landmarks_data, c.analysis_data, c.markers_data,
           c.body_scan_path, c.body_scan_url, c.body_scan_metadata,
           c.created_at, c.updated_at,
           p.first_name as patient_first_name, p.last_name as patient_last_name,
           p.mrn as patient_mrn, p.date_of_birth as patient_dob, p.gender as patient_gender
    FROM brace_cases c
    LEFT JOIN patients p ON c.patient_id = p.id
    WHERE c.case_id = ?
  `);
  
  const stepsStmt = db.prepare(`
    SELECT step_name, step_order, status, error_message, started_at, finished_at
    FROM brace_case_steps
    WHERE case_id = ?
    ORDER BY step_order ASC
  `);

  const caseData = caseStmt.get(caseId);
  if (!caseData) return null;

  const steps = stepsStmt.all(caseId);

  // Parse JSON fields
  let analysisResult = null;
  let landmarksData = null;
  let analysisData = null;
  let markersData = null;
  let bodyScanMetadata = null;

  try {
    if (caseData.analysis_result) {
      analysisResult = JSON.parse(caseData.analysis_result);
    }
  } catch (e) { /* ignore */ }

  try {
    if (caseData.landmarks_data) {
      landmarksData = JSON.parse(caseData.landmarks_data);
    }
  } catch (e) { /* ignore */ }

  try {
    if (caseData.analysis_data) {
      analysisData = JSON.parse(caseData.analysis_data);
    }
  } catch (e) { /* ignore */ }

  try {
    if (caseData.markers_data) {
      markersData = JSON.parse(caseData.markers_data);
    }
  } catch (e) { /* ignore */ }

  try {
    if (caseData.body_scan_metadata) {
      bodyScanMetadata = JSON.parse(caseData.body_scan_metadata);
    }
  } catch (e) { /* ignore */ }

  // Build patient object if patient_id exists
  const patient = caseData.patient_id ? {
    id: caseData.patient_id,
    firstName: caseData.patient_first_name,
    lastName: caseData.patient_last_name,
    fullName: `${caseData.patient_first_name} ${caseData.patient_last_name}`,
    mrn: caseData.patient_mrn,
    dateOfBirth: caseData.patient_dob,
    gender: caseData.patient_gender
  } : null;

  return {
    caseId: caseData.case_id,
    patient_id: caseData.patient_id,
    patient,
    case_type: caseData.case_type,
    visit_date: caseData.visit_date,
    status: caseData.status,
    current_step: caseData.current_step,
    notes: caseData.notes,
    analysis_result: analysisResult,
    landmarks_data: landmarksData,
    analysis_data: analysisData,
    markers_data: markersData,
    body_scan_path: caseData.body_scan_path,
    body_scan_url: caseData.body_scan_url,
    body_scan_metadata: bodyScanMetadata,
    created_at: caseData.created_at,
    updated_at: caseData.updated_at,
    steps
  };
}

/**
 * Update case status
 */
export function updateCaseStatus(caseId, status, currentStep = null) {
  const stmt = db.prepare(`
    UPDATE brace_cases 
    SET status = ?, current_step = ?, updated_at = datetime('now')
    WHERE case_id = ?
  `);
  return stmt.run(status, currentStep, caseId);
}

/**
 * Save landmarks data
 */
export function saveLandmarks(caseId, landmarksData) {
  const stmt = db.prepare(`
    UPDATE brace_cases 
    SET landmarks_data = ?, status = 'landmarks_detected', 
        current_step = 'LandmarkApproval', updated_at = datetime('now')
    WHERE case_id = ?
  `);
  return stmt.run(JSON.stringify(landmarksData), caseId);
}

/**
 * Approve landmarks
 */
export function approveLandmarks(caseId, updatedLandmarks = null) {
  const stmt = db.prepare(`
    UPDATE brace_cases 
    SET landmarks_data = COALESCE(?, landmarks_data), 
        status = 'landmarks_approved',
        current_step = 'SpineAnalysis', 
        updated_at = datetime('now')
    WHERE case_id = ?
  `);
  const data = updatedLandmarks ? JSON.stringify(updatedLandmarks) : null;
  return stmt.run(data, caseId);
}

/**
 * Save analysis result
 */
export function saveAnalysisResult(caseId, analysisResult) {
  const stmt = db.prepare(`
    UPDATE brace_cases 
    SET analysis_result = ?, status = 'analysis_complete',
        current_step = 'BraceGeneration', updated_at = datetime('now')
    WHERE case_id = ?
  `);
  return stmt.run(JSON.stringify(analysisResult), caseId);
}

/**
 * Save brace generation result
 */
export function saveBraceResult(caseId, braceResult) {
  const currentData = getCase(caseId);
  const updatedAnalysis = {
    ...(currentData?.analysis_result || {}),
    brace: braceResult
  };
  
  const stmt = db.prepare(`
    UPDATE brace_cases 
    SET analysis_result = ?, status = 'brace_generated',
        current_step = 'BraceApproval', updated_at = datetime('now')
    WHERE case_id = ?
  `);
  return stmt.run(JSON.stringify(updatedAnalysis), caseId);
}

/**
 * Save both braces generation result (regular + vase)
 */
export function saveBothBracesResult(caseId, bracesData) {
  const currentData = getCase(caseId);
  const updatedAnalysis = {
    ...(currentData?.analysis_result || {}),
    braces: bracesData.braces,
    rigoType: bracesData.rigoType,
    cobbAngles: bracesData.cobbAngles,
    bodyScanUsed: bracesData.bodyScanUsed
  };
  
  const stmt = db.prepare(`
    UPDATE brace_cases 
    SET analysis_result = ?, status = 'brace_generated',
        current_step = 'BraceApproval', updated_at = datetime('now')
    WHERE case_id = ?
  `);
  return stmt.run(JSON.stringify(updatedAnalysis), caseId);
}

/**
 * Save markers data (for brace editor)
 */
export function saveMarkers(caseId, markersData) {
  const stmt = db.prepare(`
    UPDATE brace_cases 
    SET markers_data = ?, updated_at = datetime('now')
    WHERE case_id = ?
  `);
  return stmt.run(JSON.stringify(markersData), caseId);
}

/**
 * Save analysis data (from recalculate - separate from brace result)
 */
export function saveAnalysisData(caseId, analysisData) {
  const stmt = db.prepare(`
    UPDATE brace_cases 
    SET analysis_data = ?, updated_at = datetime('now')
    WHERE case_id = ?
  `);
  return stmt.run(JSON.stringify(analysisData), caseId);
}

/**
 * Save body scan info
 * Note: We use 'analysis_complete' status for compatibility with existing databases
 * that may not have 'body_scan_uploaded' in their CHECK constraint
 */
export function saveBodyScan(caseId, scanPath, scanUrl, metadata = null) {
  const stmt = db.prepare(`
    UPDATE brace_cases 
    SET body_scan_path = ?, body_scan_url = ?, body_scan_metadata = ?,
        status = 'analysis_complete', current_step = 'BraceGeneration',
        updated_at = datetime('now')
    WHERE case_id = ?
  `);
  const metadataJson = metadata ? JSON.stringify(metadata) : null;
  return stmt.run(scanPath, scanUrl, metadataJson, caseId);
}

/**
 * Clear body scan (user wants to skip or remove)
 */
export function clearBodyScan(caseId) {
  const stmt = db.prepare(`
    UPDATE brace_cases 
    SET body_scan_path = NULL, body_scan_url = NULL, body_scan_metadata = NULL,
        updated_at = datetime('now')
    WHERE case_id = ?
  `);
  return stmt.run(caseId);
}

/**
 * Delete case
 */
export function deleteCase(caseId) {
  const stmt = db.prepare(`DELETE FROM brace_cases WHERE case_id = ?`);
  return stmt.run(caseId);
}

/**
 * Update step status
 */
export function updateStepStatus(caseId, stepName, status, errorMessage = null) {
  const stmt = db.prepare(`
    UPDATE brace_case_steps 
    SET status = ?, error_message = ?, 
        started_at = CASE WHEN ? = 'running' THEN datetime('now') ELSE started_at END,
        finished_at = CASE WHEN ? IN ('done', 'failed') THEN datetime('now') ELSE finished_at END,
        updated_at = datetime('now')
    WHERE case_id = ? AND step_name = ?
  `);
  return stmt.run(status, errorMessage, status, status, caseId, stepName);
}

// ============================================
// PATIENT MANAGEMENT
// ============================================

/**
 * Create a new patient
 */
export function createPatient(data) {
  const stmt = db.prepare(`
    INSERT INTO patients (
      mrn, first_name, last_name, date_of_birth, gender,
      email, phone, address, diagnosis, curve_type,
      medical_history, referring_physician, insurance_info, notes,
      created_by, created_at, updated_at
    )
    VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, datetime('now'), datetime('now'))
  `);
  
  const result = stmt.run(
    data.mrn || null,
    data.firstName,
    data.lastName,
    data.dateOfBirth || null,
    data.gender || null,
    data.email || null,
    data.phone || null,
    data.address || null,
    data.diagnosis || null,
    data.curveType || null,
    data.medicalHistory || null,
    data.referringPhysician || null,
    data.insuranceInfo || null,
    data.notes || null,
    data.createdBy || null
  );
  
  return {
    id: result.lastInsertRowid,
    ...data
  };
}

/**
 * Get patient by ID
 */
export function getPatient(patientId) {
  const stmt = db.prepare(`
    SELECT p.*, u.username as created_by_username
    FROM patients p
    LEFT JOIN users u ON p.created_by = u.id
    WHERE p.id = ?
  `);
  return stmt.get(patientId);
}

/**
 * List all patients with optional filters
 */
export function listPatients(options = {}) {
  const { search, isActive = true, createdBy, limit = 50, offset = 0, sortBy = 'created_at', sortOrder = 'DESC' } = options;
  
  let where = [];
  let values = [];
  
  if (isActive !== undefined && isActive !== null) {
    where.push('p.is_active = ?');
    values.push(isActive ? 1 : 0);
  }
  
  if (createdBy) {
    where.push('p.created_by = ?');
    values.push(createdBy);
  }
  
  if (search) {
    where.push('(p.first_name LIKE ? OR p.last_name LIKE ? OR p.mrn LIKE ? OR p.email LIKE ?)');
    const searchPattern = `%${search}%`;
    values.push(searchPattern, searchPattern, searchPattern, searchPattern);
  }
  
  const whereClause = where.length > 0 ? `WHERE ${where.join(' AND ')}` : '';
  const validSortColumns = ['created_at', 'updated_at', 'last_name', 'first_name', 'date_of_birth'];
  const sortColumn = validSortColumns.includes(sortBy) ? sortBy : 'created_at';
  const order = sortOrder.toUpperCase() === 'ASC' ? 'ASC' : 'DESC';
  
  // Get total count
  const countStmt = db.prepare(`SELECT COUNT(*) as count FROM patients p ${whereClause}`);
  const totalCount = countStmt.get(...values).count;
  
  // Get patients with case count
  const stmt = db.prepare(`
    SELECT p.*, 
           u.username as created_by_username,
           (SELECT COUNT(*) FROM brace_cases c WHERE c.patient_id = p.id) as case_count,
           (SELECT MAX(c.created_at) FROM brace_cases c WHERE c.patient_id = p.id) as last_visit
    FROM patients p
    LEFT JOIN users u ON p.created_by = u.id
    ${whereClause}
    ORDER BY p.${sortColumn} ${order}
    LIMIT ? OFFSET ?
  `);
  
  const patients = stmt.all(...values, limit, offset);
  
  return {
    patients,
    total: totalCount,
    limit,
    offset
  };
}

/**
 * Update patient
 */
export function updatePatient(patientId, data) {
  const fields = [];
  const values = [];
  
  if (data.mrn !== undefined) { fields.push('mrn = ?'); values.push(data.mrn); }
  if (data.firstName !== undefined) { fields.push('first_name = ?'); values.push(data.firstName); }
  if (data.lastName !== undefined) { fields.push('last_name = ?'); values.push(data.lastName); }
  if (data.dateOfBirth !== undefined) { fields.push('date_of_birth = ?'); values.push(data.dateOfBirth); }
  if (data.gender !== undefined) { fields.push('gender = ?'); values.push(data.gender); }
  if (data.email !== undefined) { fields.push('email = ?'); values.push(data.email); }
  if (data.phone !== undefined) { fields.push('phone = ?'); values.push(data.phone); }
  if (data.address !== undefined) { fields.push('address = ?'); values.push(data.address); }
  if (data.diagnosis !== undefined) { fields.push('diagnosis = ?'); values.push(data.diagnosis); }
  if (data.curveType !== undefined) { fields.push('curve_type = ?'); values.push(data.curveType); }
  if (data.medicalHistory !== undefined) { fields.push('medical_history = ?'); values.push(data.medicalHistory); }
  if (data.referringPhysician !== undefined) { fields.push('referring_physician = ?'); values.push(data.referringPhysician); }
  if (data.insuranceInfo !== undefined) { fields.push('insurance_info = ?'); values.push(data.insuranceInfo); }
  if (data.notes !== undefined) { fields.push('notes = ?'); values.push(data.notes); }
  if (data.isActive !== undefined) { fields.push('is_active = ?'); values.push(data.isActive ? 1 : 0); }
  
  if (fields.length === 0) return null;
  
  fields.push('updated_at = datetime(\'now\')');
  values.push(patientId);
  
  const stmt = db.prepare(`UPDATE patients SET ${fields.join(', ')} WHERE id = ?`);
  return stmt.run(...values);
}

/**
 * Archive patient (soft delete - set is_active = 0)
 */
export function archivePatient(patientId) {
  const stmt = db.prepare(`
    UPDATE patients 
    SET is_active = 0, updated_at = datetime('now') 
    WHERE id = ?
  `);
  return stmt.run(patientId);
}

/**
 * Unarchive patient (restore - set is_active = 1)
 */
export function unarchivePatient(patientId) {
  const stmt = db.prepare(`
    UPDATE patients 
    SET is_active = 1, updated_at = datetime('now') 
    WHERE id = ?
  `);
  return stmt.run(patientId);
}

/**
 * Delete patient - kept for backwards compatibility, now archives
 */
export function deletePatient(patientId, hard = false) {
  if (hard) {
    // Hard delete should never be used in normal operation
    const stmt = db.prepare(`DELETE FROM patients WHERE id = ?`);
    return stmt.run(patientId);
  } else {
    return archivePatient(patientId);
  }
}

/**
 * Get cases for a patient
 * @param {number} patientId - Patient ID
 * @param {Object} options - Query options
 * @param {boolean} options.includeArchived - Include archived cases
 */
export function getPatientCases(patientId, options = {}) {
  const { includeArchived = false } = options;
  
  const archivedFilter = includeArchived ? '' : 'AND is_archived = 0';
  
  const stmt = db.prepare(`
    SELECT case_id, case_type, status, current_step, visit_date, notes,
           analysis_result, landmarks_data, body_scan_path, body_scan_url,
           is_archived, archived_at, created_at, updated_at
    FROM brace_cases
    WHERE patient_id = ? ${archivedFilter}
    ORDER BY created_at DESC
  `);
  return stmt.all(patientId);
}

/**
 * Get patient statistics
 */
export function getPatientStats() {
  const total = db.prepare(`SELECT COUNT(*) as count FROM patients`).get();
  const active = db.prepare(`SELECT COUNT(*) as count FROM patients WHERE is_active = 1`).get();
  const withCases = db.prepare(`
    SELECT COUNT(DISTINCT patient_id) as count 
    FROM brace_cases 
    WHERE patient_id IS NOT NULL
  `).get();
  
  const byGender = db.prepare(`
    SELECT gender, COUNT(*) as count 
    FROM patients 
    WHERE is_active = 1 
    GROUP BY gender
  `).all();
  
  const recentPatients = db.prepare(`
    SELECT COUNT(*) as count 
    FROM patients 
    WHERE created_at >= datetime('now', '-30 days')
  `).get();
  
  return {
    total: total.count,
    active: active.count,
    inactive: total.count - active.count,
    withCases: withCases.count,
    byGender: byGender.reduce((acc, row) => { acc[row.gender || 'unspecified'] = row.count; return acc; }, {}),
    recentPatients: recentPatients.count
  };
}

// ============================================
// USER MANAGEMENT
// ============================================

/**
 * Get user by username (for login)
 */
export function getUserByUsername(username) {
  const stmt = db.prepare(`
    SELECT id, username, password_hash, email, full_name, role, is_active, last_login, created_at
    FROM users WHERE username = ?
  `);
  return stmt.get(username);
}

/**
 * Get user by ID
 */
export function getUserById(userId) {
  const stmt = db.prepare(`
    SELECT id, username, email, full_name, role, is_active, last_login, created_at, updated_at
    FROM users WHERE id = ?
  `);
  return stmt.get(userId);
}

/**
 * List all users
 */
export function listUsers() {
  const stmt = db.prepare(`
    SELECT id, username, email, full_name, role, is_active, last_login, created_at, updated_at
    FROM users ORDER BY created_at DESC
  `);
  return stmt.all();
}

/**
 * Create user
 */
export function createUser(username, passwordHash, email = null, fullName = null, role = 'user') {
  const stmt = db.prepare(`
    INSERT INTO users (username, password_hash, email, full_name, role, is_active, created_at, updated_at)
    VALUES (?, ?, ?, ?, ?, 1, datetime('now'), datetime('now'))
  `);
  const result = stmt.run(username, passwordHash, email, fullName, role);
  return { id: result.lastInsertRowid, username, email, fullName, role };
}

/**
 * Update user
 */
export function updateUser(userId, updates) {
  const fields = [];
  const values = [];
  
  if (updates.email !== undefined) { fields.push('email = ?'); values.push(updates.email); }
  if (updates.fullName !== undefined) { fields.push('full_name = ?'); values.push(updates.fullName); }
  if (updates.role !== undefined) { fields.push('role = ?'); values.push(updates.role); }
  if (updates.isActive !== undefined) { fields.push('is_active = ?'); values.push(updates.isActive ? 1 : 0); }
  if (updates.passwordHash !== undefined) { fields.push('password_hash = ?'); values.push(updates.passwordHash); }
  
  if (fields.length === 0) return null;
  
  fields.push('updated_at = datetime(\'now\')');
  values.push(userId);
  
  const stmt = db.prepare(`UPDATE users SET ${fields.join(', ')} WHERE id = ?`);
  return stmt.run(...values);
}

/**
 * Update last login
 */
export function updateLastLogin(userId) {
  const stmt = db.prepare(`UPDATE users SET last_login = datetime('now'), updated_at = datetime('now') WHERE id = ?`);
  return stmt.run(userId);
}

/**
 * Delete user
 */
export function deleteUser(userId) {
  const stmt = db.prepare(`DELETE FROM users WHERE id = ?`);
  return stmt.run(userId);
}

// ============================================
// SESSION MANAGEMENT
// ============================================

/**
 * Create session
 */
export function createSession(userId, token, expiresAt) {
  const stmt = db.prepare(`
    INSERT INTO user_sessions (user_id, session_token, expires_at, created_at)
    VALUES (?, ?, ?, datetime('now'))
  `);
  return stmt.run(userId, token, expiresAt);
}

/**
 * Get session by token
 */
export function getSessionByToken(token) {
  const stmt = db.prepare(`
    SELECT s.*, u.username, u.role, u.full_name, u.is_active
    FROM user_sessions s
    JOIN users u ON s.user_id = u.id
    WHERE s.session_token = ? AND s.expires_at > datetime('now')
  `);
  return stmt.get(token);
}

/**
 * Delete session
 */
export function deleteSession(token) {
  const stmt = db.prepare(`DELETE FROM user_sessions WHERE session_token = ?`);
  return stmt.run(token);
}

/**
 * Delete expired sessions
 */
export function cleanupExpiredSessions() {
  const stmt = db.prepare(`DELETE FROM user_sessions WHERE expires_at < datetime('now')`);
  return stmt.run();
}

// ============================================
// AUDIT LOGGING
// ============================================

/**
 * Log an action
 */
export function logAudit(userId, action, entityType, entityId = null, details = null, ipAddress = null) {
  const stmt = db.prepare(`
    INSERT INTO audit_log (user_id, action, entity_type, entity_id, details, ip_address, created_at)
    VALUES (?, ?, ?, ?, ?, ?, datetime('now'))
  `);
  return stmt.run(userId, action, entityType, entityId, details ? JSON.stringify(details) : null, ipAddress);
}

/**
 * Get audit log entries
 */
export function getAuditLog(options = {}) {
  const { userId, action, entityType, limit = 100, offset = 0 } = options;
  
  let where = [];
  let values = [];
  
  if (userId) { where.push('a.user_id = ?'); values.push(userId); }
  if (action) { where.push('a.action = ?'); values.push(action); }
  if (entityType) { where.push('a.entity_type = ?'); values.push(entityType); }
  
  const whereClause = where.length > 0 ? `WHERE ${where.join(' AND ')}` : '';
  
  const stmt = db.prepare(`
    SELECT a.*, u.username
    FROM audit_log a
    LEFT JOIN users u ON a.user_id = u.id
    ${whereClause}
    ORDER BY a.created_at DESC
    LIMIT ? OFFSET ?
  `);
  
  return stmt.all(...values, limit, offset);
}

// ============================================
// API REQUEST LOGGING
// ============================================

/**
 * Log an API request with full details
 */
export function logApiRequest(data) {
  const stmt = db.prepare(`
    INSERT INTO api_requests (
      user_id, username, method, path, route_pattern, query_params, 
      request_params, file_uploads, status_code, response_time_ms, 
      response_summary, ip_address, user_agent, request_body_size, 
      response_body_size, error_message, created_at
    )
    VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, datetime('now'))
  `);
  
  return stmt.run(
    data.userId || null,
    data.username || null,
    data.method,
    data.path,
    data.routePattern || null,
    data.queryParams ? JSON.stringify(data.queryParams) : null,
    data.requestParams ? JSON.stringify(data.requestParams) : null,
    data.fileUploads ? JSON.stringify(data.fileUploads) : null,
    data.statusCode || null,
    data.responseTimeMs || null,
    data.responseSummary ? JSON.stringify(data.responseSummary) : null,
    data.ipAddress || null,
    data.userAgent || null,
    data.requestBodySize || null,
    data.responseBodySize || null,
    data.errorMessage || null
  );
}

/**
 * Get API request logs with filters
 */
export function getApiRequests(options = {}) {
  const { 
    userId, 
    username,
    method, 
    path, 
    statusCode,
    minStatusCode,
    maxStatusCode,
    startDate,
    endDate,
    limit = 100, 
    offset = 0 
  } = options;
  
  let where = [];
  let values = [];
  
  if (userId) { where.push('user_id = ?'); values.push(userId); }
  if (username) { where.push('username LIKE ?'); values.push(`%${username}%`); }
  if (method) { where.push('method = ?'); values.push(method); }
  if (path) { where.push('path LIKE ?'); values.push(`%${path}%`); }
  if (statusCode) { where.push('status_code = ?'); values.push(statusCode); }
  if (minStatusCode) { where.push('status_code >= ?'); values.push(minStatusCode); }
  if (maxStatusCode) { where.push('status_code < ?'); values.push(maxStatusCode); }
  if (startDate) { where.push('created_at >= ?'); values.push(startDate); }
  if (endDate) { where.push('created_at <= ?'); values.push(endDate); }
  
  const whereClause = where.length > 0 ? `WHERE ${where.join(' AND ')}` : '';
  
  // Get total count
  const countStmt = db.prepare(`SELECT COUNT(*) as count FROM api_requests ${whereClause}`);
  const totalCount = countStmt.get(...values).count;
  
  // Get paginated results
  const stmt = db.prepare(`
    SELECT *
    FROM api_requests
    ${whereClause}
    ORDER BY created_at DESC
    LIMIT ? OFFSET ?
  `);
  
  const requests = stmt.all(...values, limit, offset);
  
  return {
    requests,
    total: totalCount,
    limit,
    offset
  };
}

/**
 * Get API request statistics
 */
export function getApiRequestStats(options = {}) {
  const { startDate, endDate } = options;
  
  let where = [];
  let values = [];
  
  if (startDate) { where.push('created_at >= ?'); values.push(startDate); }
  if (endDate) { where.push('created_at <= ?'); values.push(endDate); }
  
  const whereClause = where.length > 0 ? `WHERE ${where.join(' AND ')}` : '';
  
  // Total requests
  const total = db.prepare(`SELECT COUNT(*) as count FROM api_requests ${whereClause}`).get(...values);
  
  // By method
  const byMethod = db.prepare(`
    SELECT method, COUNT(*) as count 
    FROM api_requests ${whereClause}
    GROUP BY method ORDER BY count DESC
  `).all(...values);
  
  // By status code category
  const byStatusCategory = db.prepare(`
    SELECT 
      CASE 
        WHEN status_code >= 200 AND status_code < 300 THEN '2xx Success'
        WHEN status_code >= 300 AND status_code < 400 THEN '3xx Redirect'
        WHEN status_code >= 400 AND status_code < 500 THEN '4xx Client Error'
        WHEN status_code >= 500 THEN '5xx Server Error'
        ELSE 'Unknown'
      END as category,
      COUNT(*) as count
    FROM api_requests ${whereClause}
    GROUP BY category ORDER BY count DESC
  `).all(...values);
  
  // Top endpoints
  const topEndpoints = db.prepare(`
    SELECT method, path, COUNT(*) as count,
           AVG(response_time_ms) as avg_response_time
    FROM api_requests ${whereClause}
    GROUP BY method, path 
    ORDER BY count DESC 
    LIMIT 20
  `).all(...values);
  
  // Top users
  const topUsers = db.prepare(`
    SELECT user_id, username, COUNT(*) as count
    FROM api_requests 
    ${whereClause ? whereClause + ' AND username IS NOT NULL' : 'WHERE username IS NOT NULL'}
    GROUP BY user_id, username 
    ORDER BY count DESC 
    LIMIT 10
  `).all(...values);
  
  // Average response time
  const avgResponseTime = db.prepare(`
    SELECT AVG(response_time_ms) as avg, 
           MIN(response_time_ms) as min, 
           MAX(response_time_ms) as max
    FROM api_requests 
    ${whereClause ? whereClause + ' AND response_time_ms IS NOT NULL' : 'WHERE response_time_ms IS NOT NULL'}
  `).get(...values);
  
  // Requests per hour (last 24 hours)
  const requestsPerHour = db.prepare(`
    SELECT strftime('%Y-%m-%d %H:00', created_at) as hour, COUNT(*) as count
    FROM api_requests
    WHERE created_at >= datetime('now', '-24 hours')
    GROUP BY hour
    ORDER BY hour ASC
  `).all();
  
  // Error rate
  const errors = db.prepare(`
    SELECT COUNT(*) as count FROM api_requests 
    ${whereClause ? whereClause + ' AND status_code >= 400' : 'WHERE status_code >= 400'}
  `).get(...values);
  
  return {
    total: total.count,
    byMethod: byMethod.reduce((acc, row) => { acc[row.method] = row.count; return acc; }, {}),
    byStatusCategory: byStatusCategory.reduce((acc, row) => { acc[row.category] = row.count; return acc; }, {}),
    topEndpoints,
    topUsers,
    responseTime: {
      avg: Math.round(avgResponseTime?.avg || 0),
      min: avgResponseTime?.min || 0,
      max: avgResponseTime?.max || 0
    },
    requestsPerHour,
    errorRate: total.count > 0 ? Math.round((errors.count / total.count) * 100 * 10) / 10 : 0
  };
}

/**
 * Cleanup old API request logs (older than N days)
 */
export function cleanupOldApiRequests(daysToKeep = 30) {
  const stmt = db.prepare(`
    DELETE FROM api_requests 
    WHERE created_at < datetime('now', '-' || ? || ' days')
  `);
  return stmt.run(daysToKeep);
}

// ============================================
// ANALYTICS QUERIES
// ============================================

/**
 * Get case statistics
 */
export function getCaseStats() {
  const totalCases = db.prepare(`SELECT COUNT(*) as count FROM brace_cases`).get();
  const byStatus = db.prepare(`
    SELECT status, COUNT(*) as count 
    FROM brace_cases 
    GROUP BY status
  `).all();
  
  const last7Days = db.prepare(`
    SELECT DATE(created_at) as date, COUNT(*) as count
    FROM brace_cases
    WHERE created_at >= datetime('now', '-7 days')
    GROUP BY DATE(created_at)
    ORDER BY date ASC
  `).all();
  
  const last30Days = db.prepare(`
    SELECT DATE(created_at) as date, COUNT(*) as count
    FROM brace_cases
    WHERE created_at >= datetime('now', '-30 days')
    GROUP BY DATE(created_at)
    ORDER BY date ASC
  `).all();
  
  return {
    total: totalCases.count,
    byStatus: byStatus.reduce((acc, row) => { acc[row.status] = row.count; return acc; }, {}),
    last7Days,
    last30Days
  };
}

/**
 * Get Rigo classification distribution (from analysis_result JSON)
 */
export function getRigoDistribution() {
  const cases = db.prepare(`
    SELECT analysis_result FROM brace_cases 
    WHERE analysis_result IS NOT NULL AND status = 'brace_generated'
  `).all();
  
  const distribution = {};
  for (const c of cases) {
    try {
      const result = JSON.parse(c.analysis_result);
      const rigoType = result.rigoType || result.rigo_classification?.type || result.brace?.rigo_classification?.type;
      if (rigoType) {
        distribution[rigoType] = (distribution[rigoType] || 0) + 1;
      }
    } catch (e) { /* skip invalid JSON */ }
  }
  
  return distribution;
}

/**
 * Get Cobb angle statistics
 */
export function getCobbAngleStats() {
  const cases = db.prepare(`
    SELECT analysis_result, landmarks_data FROM brace_cases 
    WHERE (analysis_result IS NOT NULL OR landmarks_data IS NOT NULL)
  `).all();
  
  const angles = { PT: [], MT: [], TL: [] };
  
  for (const c of cases) {
    try {
      let cobb = null;
      
      // Try analysis_result first
      if (c.analysis_result) {
        const result = JSON.parse(c.analysis_result);
        cobb = result.cobbAngles || result.cobb_angles || result.brace?.cobb_angles;
      }
      
      // Fall back to landmarks_data
      if (!cobb && c.landmarks_data) {
        const landmarks = JSON.parse(c.landmarks_data);
        cobb = landmarks.cobb_angles;
      }
      
      if (cobb) {
        if (cobb.PT !== undefined) angles.PT.push(cobb.PT);
        if (cobb.MT !== undefined) angles.MT.push(cobb.MT);
        if (cobb.TL !== undefined) angles.TL.push(cobb.TL);
      }
    } catch (e) { /* skip invalid JSON */ }
  }
  
  const calcStats = (arr) => {
    if (arr.length === 0) return { min: 0, max: 0, avg: 0, count: 0 };
    const sum = arr.reduce((a, b) => a + b, 0);
    return {
      min: Math.min(...arr),
      max: Math.max(...arr),
      avg: Math.round((sum / arr.length) * 10) / 10,
      count: arr.length
    };
  };
  
  return {
    PT: calcStats(angles.PT),
    MT: calcStats(angles.MT),
    TL: calcStats(angles.TL),
    totalCasesWithAngles: Math.max(angles.PT.length, angles.MT.length, angles.TL.length)
  };
}

/**
 * Get processing time statistics
 */
export function getProcessingTimeStats() {
  const cases = db.prepare(`
    SELECT analysis_result FROM brace_cases 
    WHERE analysis_result IS NOT NULL AND status = 'brace_generated'
  `).all();
  
  const times = [];
  
  for (const c of cases) {
    try {
      const result = JSON.parse(c.analysis_result);
      const time = result.processing_time_ms || result.brace?.processing_time_ms;
      if (time) times.push(time);
    } catch (e) { /* skip invalid JSON */ }
  }
  
  if (times.length === 0) {
    return { min: 0, max: 0, avg: 0, count: 0 };
  }
  
  const sum = times.reduce((a, b) => a + b, 0);
  return {
    min: Math.min(...times),
    max: Math.max(...times),
    avg: Math.round(sum / times.length),
    count: times.length
  };
}

/**
 * Get body scan usage stats
 */
export function getBodyScanStats() {
  const total = db.prepare(`SELECT COUNT(*) as count FROM brace_cases WHERE status = 'brace_generated'`).get();
  const withScan = db.prepare(`SELECT COUNT(*) as count FROM brace_cases WHERE status = 'brace_generated' AND body_scan_path IS NOT NULL`).get();
  
  return {
    total: total.count,
    withBodyScan: withScan.count,
    withoutBodyScan: total.count - withScan.count,
    percentage: total.count > 0 ? Math.round((withScan.count / total.count) * 100) : 0
  };
}

/**
 * Get user statistics
 */
export function getUserStats() {
  const total = db.prepare(`SELECT COUNT(*) as count FROM users`).get();
  const byRole = db.prepare(`SELECT role, COUNT(*) as count FROM users GROUP BY role`).all();
  const active = db.prepare(`SELECT COUNT(*) as count FROM users WHERE is_active = 1`).get();
  const recentLogins = db.prepare(`
    SELECT COUNT(*) as count FROM users 
    WHERE last_login >= datetime('now', '-7 days')
  `).get();
  
  return {
    total: total.count,
    active: active.count,
    inactive: total.count - active.count,
    byRole: byRole.reduce((acc, row) => { acc[row.role] = row.count; return acc; }, {}),
    recentLogins: recentLogins.count
  };
}

/**
 * List cases with filters (for admin)
 */
export function listCasesFiltered(options = {}) {
  const { status, createdBy, search, limit = 50, offset = 0, sortBy = 'created_at', sortOrder = 'DESC', includeArchived = false, archivedOnly = false } = options;
  
  let where = [];
  let values = [];
  
  if (status) { where.push('c.status = ?'); values.push(status); }
  if (createdBy) { where.push('c.created_by = ?'); values.push(createdBy); }
  if (search) { where.push('c.case_id LIKE ?'); values.push(`%${search}%`); }
  
  // Archive filtering
  if (archivedOnly) {
    where.push('c.is_archived = 1');
  } else if (!includeArchived) {
    where.push('c.is_archived = 0');
  }
  
  const whereClause = where.length > 0 ? `WHERE ${where.join(' AND ')}` : '';
  const validSortColumns = ['created_at', 'updated_at', 'status', 'case_id'];
  const sortColumn = validSortColumns.includes(sortBy) ? sortBy : 'created_at';
  const order = sortOrder.toUpperCase() === 'ASC' ? 'ASC' : 'DESC';
  
  const countStmt = db.prepare(`SELECT COUNT(*) as count FROM brace_cases c ${whereClause}`);
  const totalCount = countStmt.get(...values).count;
  
  const stmt = db.prepare(`
    SELECT c.case_id as caseId, c.case_type, c.status, c.current_step, c.notes,
           c.analysis_result, c.landmarks_data, c.body_scan_path,
           c.is_archived, c.archived_at,
           c.created_by, c.created_at, c.updated_at,
           u.username as created_by_username
    FROM brace_cases c
    LEFT JOIN users u ON c.created_by = u.id
    ${whereClause}
    ORDER BY c.${sortColumn} ${order}
    LIMIT ? OFFSET ?
  `);
  
  const cases = stmt.all(...values, limit, offset).map(row => ({
    ...row,
    is_archived: row.is_archived === 1
  }));
  
  return {
    cases,
    total: totalCount,
    limit,
    offset
  };
}

export default {
  // Case management
  createCase,
  listCases,
  listCasesFiltered,
  getCase,
  updateCaseStatus,
  saveLandmarks,
  approveLandmarks,
  saveAnalysisResult,
  saveAnalysisData,
  saveBraceResult,
  saveBothBracesResult,
  saveMarkers,
  saveBodyScan,
  clearBodyScan,
  deleteCase,
  archiveCase,
  unarchiveCase,
  updateStepStatus,
  STEP_NAMES,
  // Patient management
  createPatient,
  getPatient,
  listPatients,
  updatePatient,
  deletePatient,
  archivePatient,
  unarchivePatient,
  getPatientCases,
  getPatientStats,
  // User management
  getUserByUsername,
  getUserById,
  listUsers,
  createUser,
  updateUser,
  updateLastLogin,
  deleteUser,
  // Session management
  createSession,
  getSessionByToken,
  deleteSession,
  cleanupExpiredSessions,
  // Audit logging
  logAudit,
  getAuditLog,
  // API request logging
  logApiRequest,
  getApiRequests,
  getApiRequestStats,
  cleanupOldApiRequests,
  // Analytics
  getCaseStats,
  getRigoDistribution,
  getCobbAngleStats,
  getProcessingTimeStats,
  getBodyScanStats,
  getUserStats
};
