import type { ExtensionAPI, ToolInfo } from '@earendil-works/pi-coding-agent';
import { fileURLToPath } from 'node:url';
import { homedir } from 'node:os';
import * as fs from 'node:fs';
import * as path from 'node:path';

// Resolve the pi-coding-agent package directory
// Search in: project node_modules, then global mise node_modules
function findPkgDir(): string {
  // Try project node_modules first
  const projectPkg = path.join(process.cwd(), 'node_modules', '@earendil-works', 'pi-coding-agent');
  if (fs.existsSync(projectPkg)) return projectPkg;

  // Try global mise node_modules
  const home = homedir();
  const globalPkg = path.join(
    home,
    '.local',
    'share',
    'mise',
    'installs',
    'node',
    '*',
    'lib',
    'node_modules',
    '@earendil-works',
    'pi-coding-agent',
  );
  const matches = fs
    .readdirSync(path.join(home, '.local', 'share', 'mise', 'installs', 'node'))
    .filter((d) =>
      fs.existsSync(path.join(home, '.local', 'share', 'mise', 'installs', 'node', d)),
    );
  for (const version of matches) {
    const candidate = path.join(
      home,
      '.local',
      'share',
      'mise',
      'installs',
      'node',
      version,
      'lib',
      'node_modules',
      '@earendil-works',
      'pi-coding-agent',
    );
    if (fs.existsSync(candidate)) return candidate;
  }

  // Fallback: try the directory of the loaded module
  const extPath = fileURLToPath(import.meta.url);
  let dir = extPath;
  for (let i = 0; i < 20; i++) {
    const candidate = path.join(dir, 'node_modules', '@earendil-works', 'pi-coding-agent');
    if (fs.existsSync(candidate)) return candidate;
    const parent = path.dirname(dir);
    if (parent === dir) break;
    dir = parent;
  }

  throw new Error('Could not find @earendil-works/pi-coding-agent package');
}

const pkgDir = findPkgDir();
const exportHtmlModule = await import(path.join(pkgDir, 'dist', 'core', 'export-html', 'index.js'));
const { exportSessionToHtml } = exportHtmlModule;

export default function (pi: ExtensionAPI) {
  pi.registerCommand('clear', {
    description: 'Export session to transcripts/ and start a new session',
    handler: async (_args, ctx) => {
      if (ctx.mode !== 'tui') {
        ctx.ui.notify('clear requires interactive mode', 'error');
        return;
      }

      // Prompt for transcript name
      const name = await ctx.ui.input('Clear & Export', 'Transcript name (spaces become dashes)', {
        timeout: 60000,
      });
      if (!name || !name.trim()) {
        ctx.ui.notify('Clear & Export cancelled', 'info');
        return;
      }

      // Sanitize: spaces → dashes, ensure .html extension
      const sanitizedName = name.trim().replace(/\s+/g, '-');
      const fileName = sanitizedName.endsWith('.html') ? sanitizedName : `${sanitizedName}.html`;

      // Build output path in transcripts/
      const transcriptsDir = path.join(ctx.cwd, 'transcripts');
      const outputPath = path.join(transcriptsDir, fileName);

      // Ensure transcripts directory exists
      if (!fs.existsSync(transcriptsDir)) {
        fs.mkdirSync(transcriptsDir, { recursive: true });
      }

      // Get session file path
      const sessionFile = ctx.sessionManager.getSessionFile();
      if (!sessionFile) {
        ctx.ui.notify('No session to export', 'error');
        return;
      }

      // Build state from in-memory data (not available in a separate pi process)
      const state = {
        systemPrompt: ctx.getSystemPrompt(),
        tools: pi.getAllTools(),
      };

      // Export session to HTML with full in-memory state
      await exportSessionToHtml(ctx.sessionManager, state, { outputPath });

      ctx.ui.notify(`Exported to: transcripts/${fileName}`, 'info');

      // Start a new session
      const currentSessionFile = ctx.sessionManager.getSessionFile();
      const newResult = await ctx.newSession({
        parentSession: currentSessionFile,
        withSession: (replacementCtx) => {
          replacementCtx.ui.notify('Session cleared and exported', 'info');
        },
      });

      if (newResult.cancelled) {
        ctx.ui.notify('New session cancelled', 'info');
      }
    },
  });
}
