import assert from 'node:assert/strict';
import fs from 'node:fs/promises';
import os from 'node:os';
import path from 'node:path';
import test from 'node:test';
import {
  createWorkspaceAssetSync,
  listWorkspaceZoneFiles,
  shouldSyncWorkspaceFilename,
} from './mindspace-workspace-sync.mjs';
import { resolveUserWorkspaceRoot } from './user-space.mjs';

test('shouldSyncWorkspaceFilename skips helper files', () => {
  assert.equal(shouldSyncWorkspaceFilename('端午感怀.docx'), true);
  assert.equal(shouldSyncWorkspaceFilename('index.html'), false);
  assert.equal(shouldSyncWorkspaceFilename('note.thumbnail.svg'), false);
});

test('listWorkspaceZoneFiles returns only supported top-level zone files', async () => {
  const h5Root = await fs.mkdtemp(path.join(os.tmpdir(), 'h5-sync-'));
  const workspace = resolveUserWorkspaceRoot(h5Root, { id: 'user-1', username: 'john' });
  await fs.mkdir(path.join(workspace, 'oa'), { recursive: true });
  await fs.writeFile(path.join(workspace, 'oa', 'report.csv'), 'a,b\n1,2\n');
  await fs.writeFile(path.join(workspace, 'oa', 'index.html'), '<html></html>');
  await fs.writeFile(path.join(workspace, 'oa', 'note.txt'), 'hello');

  const files = await listWorkspaceZoneFiles(workspace, 'oa');
  assert.deepEqual(
    files.map((item) => item.filename).sort(),
    ['note.txt', 'report.csv'],
  );
});

test('syncUserWorkspace imports new workspace files into asset library', async () => {
  const h5Root = await fs.mkdtemp(path.join(os.tmpdir(), 'h5-sync-'));
  const storageRoot = path.join(h5Root, 'data', 'mindspace');
  const workspace = resolveUserWorkspaceRoot(h5Root, { id: 'user-1', username: 'john' });
  await fs.mkdir(path.join(workspace, 'oa'), { recursive: true });
  await fs.writeFile(path.join(workspace, 'oa', 'memo.txt'), 'hello workspace\n');

  const state = {
    users: [{ id: 'user-1', username: 'john' }],
    categories: [
      { id: 'cat-1', user_id: 'user-1', space_id: 'space-1', category_code: 'oa' },
    ],
    spaces: [
      {
        id: 'space-1',
        user_id: 'user-1',
        quota_bytes: 5 * 1024 * 1024,
        used_bytes: 0,
        reserved_bytes: 0,
        status: 'active',
      },
    ],
    assets: [],
    versions: [],
  };

  let nextId = 0;
  const pool = {
    async query(sql, params = []) {
      if (sql.includes('SELECT username FROM h5_users')) {
        return [[{ username: 'john' }]];
      }
      if (sql.includes('FROM h5_space_categories c') && sql.includes('category_code = ?')) {
        const category = state.categories.find(
          (item) => item.user_id === params[0] && item.category_code === params[1],
        );
        return [category ? [category] : []];
      }
      if (sql.includes('FROM h5_assets')) {
        const assets = state.assets.filter((item) => {
          if (item.user_id !== params[0] || item.category_id !== params[1]) return false;
          if (sql.includes("status <> 'deleted'") && item.status === 'deleted') return false;
          if (sql.includes("status = 'deleted'") && item.status !== 'deleted') return false;
          if (sql.includes("source_type = 'workspace'") && item.source_type !== 'workspace') {
            return false;
          }
          return true;
        });
        return [assets];
      }
      return [[]];
    },
    async getConnection() {
      return {
        async beginTransaction() {},
        async commit() {},
        async rollback() {},
        release() {},
        async query(sql, params = []) {
          if (sql.includes('FROM h5_user_spaces') && sql.includes('FOR UPDATE')) {
            const space = state.spaces.find(
              (item) => item.id === params[0] && item.user_id === params[1],
            );
            return [space ? [space] : []];
          }
          if (sql.includes('INSERT INTO h5_assets')) {
            state.assets.push({
              id: params[0],
              user_id: params[1],
              category_id: params[3],
              original_filename: params[6],
              checksum: params[10],
              size_bytes: params[9],
              current_version_id: params[8],
              status: params[13],
              source_type: 'workspace',
            });
            return [[]];
          }
          if (sql.includes('INSERT INTO h5_asset_versions')) {
            state.versions.push({
              id: params[0],
              asset_id: params[1],
              storage_key: params[2],
              scan_status: params[7],
            });
            return [[]];
          }
          if (sql.includes('used_bytes = used_bytes +')) {
            state.spaces[0].used_bytes += params[0];
            return [[]];
          }
          if (sql.includes('COALESCE(MAX(version_no)')) {
            return [[{ max_version: 0 }]];
          }
          return pool.query(sql, params);
        },
      };
    },
  };

  const sync = createWorkspaceAssetSync({
    pool,
    storageRoot,
    h5Root,
    maxFileBytes: 1024 * 1024,
    idFactory: () => `id-${++nextId}`,
  });

  const result = await sync.syncUserWorkspace('user-1', { categoryCode: 'oa' });
  assert.equal(result.imported, 1);
  assert.equal(state.assets.length, 1);
  assert.equal(state.assets[0].original_filename, 'memo.txt');
  assert.ok(state.versions.length === 1);
  const stored = path.join(storageRoot, state.versions[0].storage_key);
  assert.equal(await fs.readFile(stored, 'utf8'), 'hello workspace\n');
});
