// ============================================================
// MEMORIES ROUTES — User template/memory storage
// ============================================================

import express = require('express');
import type { Request, Response } from 'express';
const db = require('../db/database');
const { authMiddleware } = require('../middleware/auth');
const logger = require('../utils/logger');
const cryptoUtil = require('../utils/crypto');

const router = express.Router();
router.use(authMiddleware);

function decryptMemory(row: any): any {
  if (!row) return row;
  try { row.name = cryptoUtil.decryptString(row.name); } catch (e) {}
  try { row.content = cryptoUtil.decryptString(row.content); } catch (e) {}
  return row;
}

const VALID_CATEGORIES: string[] = [
  'physical_exam', 'ros', 'encounter_format', 'family_history', 'assessment_plan', 'custom',
  'template_soap', 'template_hpi', 'template_wellvisit', 'template_sickvisit',
  'correction_soap', 'correction_hpi', 'correction_encounter', 'correction_wellvisit', 'correction_sickvisit',
];

router.get('/memories', async function (req: Request, res: Response) {
  try {
    const rows = await db.all(
      'SELECT id, category, name, content, created_at, updated_at FROM user_memories WHERE user_id = $1 ORDER BY category, id',
      [req.user!.id]
    );
    rows.forEach(decryptMemory);
    res.json({ success: true, memories: rows });
  } catch (e: any) { logger.error('GET /memories', e.message); res.status(500).json({ error: 'Request failed' }); }
});

router.post('/memories', async function (req: Request, res: Response) {
  try {
    const { name, category, content } = req.body;
    if (!name || !name.trim()) return res.status(400).json({ error: 'Name required' });
    if (!content || !content.trim()) return res.status(400).json({ error: 'Content required' });
    const cat = VALID_CATEGORIES.includes(category) ? category : 'custom';

    const count = await db.get('SELECT COUNT(*) as cnt FROM user_memories WHERE user_id = $1', [req.user!.id]);
    if (count && parseInt(count.cnt) >= 200) return res.status(400).json({ error: 'Maximum 200 memories per user' });

    const result = await db.run(
      'INSERT INTO user_memories (user_id, category, name, content) VALUES ($1,$2,$3,$4)',
      [
        req.user!.id,
        cat,
        cryptoUtil.encryptString(name.trim().substring(0, 100)),
        cryptoUtil.encryptString(content.trim().substring(0, 5000)),
      ]
    );
    res.json({ success: true, id: result.lastInsertRowid });
  } catch (e: any) { logger.error('POST /memories', e.message); res.status(500).json({ error: 'Request failed' }); }
});

router.put('/memories/:id', async function (req: Request, res: Response) {
  try {
    const { name, category, content } = req.body;
    const cat = VALID_CATEGORIES.includes(category) ? category : 'custom';
    await db.run(
      'UPDATE user_memories SET name=$1, category=$2, content=$3, updated_at=NOW() WHERE id=$4 AND user_id=$5',
      [
        cryptoUtil.encryptString((name || '').trim().substring(0, 100)),
        cat,
        cryptoUtil.encryptString((content || '').trim().substring(0, 5000)),
        req.params.id,
        req.user!.id,
      ]
    );
    res.json({ success: true });
  } catch (e: any) { logger.error('PUT /memories/:id', e.message); res.status(500).json({ error: 'Request failed' }); }
});

router.delete('/memories/:id', async function (req: Request, res: Response) {
  try {
    await db.run('DELETE FROM user_memories WHERE id = $1 AND user_id = $2', [req.params.id, req.user!.id]);
    res.json({ success: true });
  } catch (e: any) { logger.error('DELETE /memories/:id', e.message); res.status(500).json({ error: 'Request failed' }); }
});

router.get('/memories/context', async function (req: Request, res: Response) {
  try {
    const rows = await db.all(
      'SELECT category, name, content FROM user_memories WHERE user_id = $1 ORDER BY category',
      [req.user!.id]
    );
    if (rows.length === 0) return res.json({ success: true, context: '' });
    rows.forEach(decryptMemory);

    const templates: any[] = [];
    const corrections: any[] = [];
    rows.forEach((r: any) => {
      if (r.category.startsWith('correction_')) corrections.push(r);
      else templates.push(r);
    });

    let context = '';
    if (templates.length > 0) {
      context += '\n\nPHYSICIAN TEMPLATES AND PREFERENCES:\n';
      templates.forEach((r) => {
        context += '--- ' + r.category.toUpperCase().replace(/_/g, ' ') + ': ' + r.name + ' ---\n' + r.content + '\n\n';
      });
    }
    if (corrections.length > 0) {
      context += '\n\nSTYLE CORRECTIONS (these are examples of past edits — use only the writing style, never the clinical content):\n';
      corrections.slice(-10).forEach((r) => {
        const lines = r.content.split('\n').filter((l: string) => l.trim());
        let orig = '', corr = '';
        let inCorrected = false;
        lines.forEach((l: string) => {
          if (l.startsWith('CORRECTED TO:')) { inCorrected = true; corr = l.replace('CORRECTED TO:', '').trim(); }
          else if (l.startsWith('ORIGINAL:')) { orig = l.replace('ORIGINAL:', '').trim(); }
          else if (inCorrected) { corr += ' ' + l.trim(); }
          else { orig += ' ' + l.trim(); }
        });
        orig = orig.substring(0, 200);
        corr = corr.substring(0, 200);
        if (orig && corr) {
          context += '- Before: "' + orig + '..."\n  After: "' + corr + '..."\n';
        }
      });
    }
    res.json({ success: true, context: context.trim() });
  } catch (e: any) { logger.error('GET /memories/context', e.message); res.status(500).json({ error: 'Request failed' }); }
});

router.post('/memories/correction', async function (req: Request, res: Response) {
  try {
    const { section, original_snippet, corrected_snippet } = req.body;
    if (!section || !original_snippet || !corrected_snippet) {
      return res.status(400).json({ error: 'section, original_snippet, and corrected_snippet required' });
    }
    if (original_snippet.trim() === corrected_snippet.trim()) {
      return res.json({ success: true, skipped: true });
    }
    let cat = 'correction_' + section;
    if (!VALID_CATEGORIES.includes(cat)) cat = 'correction_encounter';

    const existing = await db.all(
      'SELECT id FROM user_memories WHERE user_id = $1 AND category = $2 ORDER BY created_at ASC',
      [req.user!.id, cat]
    );
    if (existing.length >= 20) {
      const toDelete = existing.slice(0, existing.length - 19);
      for (const row of toDelete) {
        await db.run('DELETE FROM user_memories WHERE id = $1 AND user_id = $2', [row.id, req.user!.id]);
      }
    }

    const name = original_snippet.substring(0, 60).replace(/\n/g, ' ') + '...';
    const content = 'ORIGINAL: ' + original_snippet.substring(0, 2000) + '\nCORRECTED TO: ' + corrected_snippet.substring(0, 2000);

    await db.run(
      'INSERT INTO user_memories (user_id, category, name, content) VALUES ($1,$2,$3,$4)',
      [req.user!.id, cat, cryptoUtil.encryptString(name), cryptoUtil.encryptString(content)]
    );
    res.json({ success: true });
  } catch (e: any) { logger.error('POST /memories/correction', e.message); res.status(500).json({ error: 'Request failed' }); }
});

export = router;
