import { Plugin } from 'unified';
import { Node, Parent } from 'unist';
import { Text } from 'mdast';
import { visit } from 'unist-util-visit';
import { execSync } from 'child_process';
import { existsSync } from 'fs';
import { join } from 'path';
import { importMarkdownSection } from '../markdownImporter';
import { importCodeSymbols } from '../codeImporter';

interface MeldDirectiveNode extends Node {
  type: 'meldDirective';
  meldType: 'cmd' | 'import';
  data?: {
    command?: string;
    importPath?: string;
    heading?: string;
    headingLevelOverride?: string;
    headingTextOverride?: string;
    importSymbolList?: string[];
    importWholeFile?: boolean;
  };
}

interface ProcessMeldNodesOptions {
  currentFileDir: string;
  debug?: boolean;
  detailedErrors?: boolean;
}

export const remarkProcessMeldNodes: Plugin<[ProcessMeldNodesOptions]> = function (options: ProcessMeldNodesOptions) {
  return async function transformer(tree: Node, file: any) {
    const errors: string[] = [];

    // Initialize meldErrors in file.data
    file.data = file.data || {};
    file.data.meldErrors = [];

    visit(tree, 'meldDirective', (node: MeldDirectiveNode, index, parent: Parent) => {
      if (options.debug) {
        console.log('Visiting node:', {
          type: node.type,
          meldType: node.meldType,
          index,
          parentType: parent?.type,
          parentChildren: parent?.children?.length
        });
      }

      if (index === null || index === undefined) {
        if (options.debug) console.log('Skipping node due to null/undefined index');
        return;
      }

      try {
        if (node.meldType === 'cmd') {
          if (options.debug) console.log('Processing command:', node.data?.command);
          try {
            const output = execSync(node.data?.command || '', { 
              encoding: 'utf-8',
              cwd: options.currentFileDir,
              stdio: ['pipe', 'pipe', 'pipe']
            }).trim();

            if (options.debug) {
              console.log('Command output:', output);
              console.log('Replacing node at index', index);
            }

            // Replace with a text node containing the output
            parent.children[index] = {
              type: 'text',
              value: output
            } as Text;

            if (options.debug) console.log('Node replaced, new node:', parent.children[index]);
          } catch (cmdError: any) {
            const errorMessage = options.detailedErrors
              ? 'Command produced error output (included below)\n' + 
                (cmdError.stderr || cmdError.message || 'Unknown error')
              : 'Error: Error processing cmd directive';
            parent.children[index] = {
              type: 'text',
              value: errorMessage
            } as Text;
            file.data.meldErrors.push(errorMessage);
          }
        } else {
          // It's an import directive
          const importPath = node.data?.importPath;
          if (options.debug) console.log('Processing import:', importPath, 'heading:', node.data?.heading);
          if (!importPath) {
            throw new Error('Invalid import directive: missing import path');
          }

          // Logic to figure out if it's a .md or .ts
          if (importPath.endsWith('.md')) {
            const heading = node.data?.heading;
            // Reuse existing markdownImporter
            try {
              const resolvedPath = join(options.currentFileDir, importPath);
              if (!existsSync(resolvedPath)) {
                throw new Error('File not found');
              }

              const result = importMarkdownSection({
                filePath: resolvedPath,
                heading,
                headingLevelOverride: node.data?.headingLevelOverride,
                headingTextOverride: node.data?.headingTextOverride
              });
              if (!result.headingFound && heading) {
                throw new Error(`Heading "${heading}" not found in ${importPath}`);
              }

              parent.children[index] = {
                type: 'text',
                value: result.content
              } as Text;
            } catch (error) {
              throw new Error(`Error processing import directive: ${(error as Error).message}`);
            }
          } else {
            // Assume it's a code file
            try {
              const resolvedPath = join(options.currentFileDir, importPath);
              if (!existsSync(resolvedPath)) {
                throw new Error('File not found');
              }

              const result = importCodeSymbols({
                filePath: resolvedPath,
                symbolList: node.data?.importSymbolList || [],
                headingLevelOverride: node.data?.headingLevelOverride,
                headingTextOverride: node.data?.headingTextOverride
              });

              if (result.content.trim() === '') {
                const errorMessage = 'Error: Error processing import directive';
                parent.children[index] = {
                  type: 'text',
                  value: errorMessage
                } as Text;
                file.data.meldErrors.push(errorMessage);
              } else {
                parent.children[index] = {
                  type: 'text',
                  value: result.content
                } as Text;
              }
            } catch (error) {
              throw new Error(`Error processing import directive: ${(error as Error).message}`);
            }
          }
        }
      } catch (error) {
        const errorMessage = `Error: ${(error as Error).message}\n\n`;
        parent.children[index] = {
          type: 'text',
          value: errorMessage
        } as Text;
        file.data.meldErrors.push(errorMessage);
      }
    });

    return tree;
  };
}; 