import { readFileSync, existsSync } from 'fs';

/**
 * Metadata Extractor - Parse markdown documents into structured JSON
 *
 * Generates quick summaries for LLM to parse, reducing token usage
 * by 60-80% compared to reading full markdown files.
 */

/**
 * Extract a field value from markdown content (table or colon format)
 * @param {string} content - Markdown content
 * @param {string} fieldName - Field name to extract
 * @returns {string|null} Field value or null
 */
function extractField(content, fieldName) {
  // Try table row format first: | FieldName | Value |
  const tableRegex = new RegExp(`\\|\\s*${fieldName}\\s*\\|\\s*(.+?)\\s*\\|`, 'i');
  const tableMatch = content.match(tableRegex);
  if (tableMatch) {
    return tableMatch[1].trim();
  }

  // Try colon format: FieldName: Value
  const colonRegex = new RegExp(`^${fieldName}\\s*:\\s*(.+)$`, 'im');
  const colonMatch = content.match(colonRegex);
  return colonMatch ? colonMatch[1].trim() : null;
}

/**
 * Extract first paragraph from a section
 * @param {string} content - Markdown content
 * @param {string} sectionHeader - Section header (e.g., "## Overview")
 * @returns {string|null} First paragraph or null
 */
function extractFirstParagraph(content, sectionHeader) {
  const regex = new RegExp(`${sectionHeader}\\s+([^\\n]+(?:\\n(?!##)[^\\n]+)*)`, 'i');
  const match = content.match(regex);

  if (!match) return null;

  // Get first paragraph (up to first blank line or next section)
  const text = match[1].trim();
  const firstPara = text.split('\n\n')[0];
  return firstPara.substring(0, 300); // Limit to 300 chars
}

/**
 * Extract bullet points from a section
 * @param {string} content - Markdown content
 * @param {string} sectionHeader - Section header
 * @returns {string[]} Array of bullet points
 */
function extractBulletPoints(content, sectionHeader) {
  const regex = new RegExp(`${sectionHeader}([\\s\\S]*?)(?=\\n## |$)`, 'i');
  const match = content.match(regex);

  if (!match) return [];

  const sectionContent = match[1];
  const bullets = [];

  // Match lines starting with -, *, or numbered list
  const bulletRegex = /^[\s]*[-*][\s]+(.+)$/gm;
  let bulletMatch;

  while ((bulletMatch = bulletRegex.exec(sectionContent)) !== null) {
    bullets.push(bulletMatch[1].trim());
  }

  return bullets.slice(0, 10); // Limit to 10 items
}

/**
 * Extract table or list from a section
 * @param {string} content - Markdown content
 * @param {string} sectionHeader - Section header
 * @returns {string[]} Array of items
 */
function extractTableOrList(content, sectionHeader) {
  const items = extractBulletPoints(content, sectionHeader);

  if (items.length > 0) return items;

  // Try extracting table rows
  const regex = new RegExp(`${sectionHeader}([\\s\\S]*?)(?=\\n## |$)`, 'i');
  const match = content.match(regex);

  if (!match) return [];

  const sectionContent = match[1];
  const tableRows = [];

  // Match table rows (| col1 | col2 |)
  const rowRegex = /^\|(.+)\|$/gm;
  let rowMatch;

  while ((rowMatch = rowRegex.exec(sectionContent)) !== null) {
    const row = rowMatch[1].trim();
    // Skip header separator rows
    if (!row.match(/^[-:|\s]+$/)) {
      tableRows.push(row);
    }
  }

  return tableRows.slice(0, 10); // Limit to 10 rows
}

/**
 * Auto-generate tags from content
 * @param {string} content - Markdown content
 * @returns {string[]} Array of tags
 */
function autoGenerateTags(content) {
  const tags = new Set();
  const lowerContent = content.toLowerCase();

  // Technology tags
  const techKeywords = {
    'blazor': 'blazor',
    'react': 'react',
    'nextjs': 'nextjs',
    'next.js': 'nextjs',
    'azure': 'azure',
    'sql': 'database',
    'entity framework': 'ef-core',
    'hangfire': 'background-jobs',
    'signalr': 'realtime',
    'docker': 'container',
    'bicep': 'infrastructure-as-code',
    'api': 'api',
    'rest': 'rest-api',
    'authentication': 'auth',
    'authorization': 'auth'
  };

  Object.entries(techKeywords).forEach(([keyword, tag]) => {
    if (lowerContent.includes(keyword)) {
      tags.add(tag);
    }
  });

  return Array.from(tags).slice(0, 8); // Limit to 8 tags
}

/**
 * Extract spec.md metadata
 * @param {string} specPath - Path to spec.md file
 * @returns {Object} Spec metadata
 */
export function extractSpecMetadata(specPath) {
  if (!existsSync(specPath)) {
    return {
      error: 'Spec file not found',
      path: specPath
    };
  }

  try {
    const content = readFileSync(specPath, 'utf8');

    return {
      id: extractField(content, 'ID') || extractField(content, 'Feature'),
      status: extractField(content, 'Status'),
      complexity: extractField(content, 'Complexity'),
      estimatedCost: extractField(content, 'Estimated Cost') || extractField(content, 'Cost'),

      summary: {
        problem: extractFirstParagraph(content, '## Overview') ||
                 extractFirstParagraph(content, '## Problem Statement'),
        solution: extractFirstParagraph(content, '## Proposed Solution') ||
                  extractFirstParagraph(content, '## Solution'),
        tags: autoGenerateTags(content)
      },

      requirements: extractBulletPoints(content, '## Requirements').slice(0, 5),
      dataModel: extractTableOrList(content, '## Data Model').slice(0, 5),
      apiContracts: extractTableOrList(content, '## API Contracts').slice(0, 5),

      stats: {
        length: content.length,
        sections: (content.match(/^## /gm) || []).length,
        codeBlocks: (content.match(/```/g) || []).length / 2
      },

      generatedAt: new Date().toISOString(),
      source: specPath
    };
  } catch (error) {
    return {
      error: error.message,
      path: specPath
    };
  }
}

/**
 * Extract proposal.md metadata
 * @param {string} proposalPath - Path to proposal.md file
 * @returns {Object} Proposal metadata
 */
export function extractProposalMetadata(proposalPath) {
  if (!existsSync(proposalPath)) {
    return {
      error: 'Proposal file not found',
      path: proposalPath
    };
  }

  try {
    const content = readFileSync(proposalPath, 'utf8');

    return {
      id: extractField(content, 'ID') || extractField(content, 'Feature'),
      status: extractField(content, 'Status'),

      summary: {
        problem: extractFirstParagraph(content, '## Problem Statement'),
        solution: extractFirstParagraph(content, '## Proposed Solution'),
        tags: autoGenerateTags(content)
      },

      successMetrics: extractBulletPoints(content, '## Success Metrics').slice(0, 5),

      generatedAt: new Date().toISOString(),
      source: proposalPath
    };
  } catch (error) {
    return {
      error: error.message,
      path: proposalPath
    };
  }
}

/**
 * Extract decisions.md metadata (ADRs)
 * @param {string} decisionsPath - Path to decisions.md file
 * @returns {Object} Decisions metadata
 */
export function extractDecisionsMetadata(decisionsPath) {
  if (!existsSync(decisionsPath)) {
    return {
      error: 'Decisions file not found',
      path: decisionsPath
    };
  }

  try {
    const content = readFileSync(decisionsPath, 'utf8');
    const decisions = [];

    // Match ADR pattern: ### ADR-001: Title
    const adrRegex = /### (ADR-\d+): (.+?)\n([\s\S]*?)(?=### ADR-|\n## |$)/g;
    let match;

    while ((match = adrRegex.exec(content)) !== null) {
      const [, id, title, body] = match;

      decisions.push({
        id,
        title: title.trim(),
        summary: body.trim().substring(0, 200), // First 200 chars
        fullPath: `${decisionsPath}#${id.toLowerCase()}`
      });
    }

    return {
      decisions,
      total: decisions.length,
      generatedAt: new Date().toISOString(),
      source: decisionsPath
    };
  } catch (error) {
    return {
      error: error.message,
      path: decisionsPath
    };
  }
}

/**
 * Extract tasks.json metadata (summary only)
 * @param {string} tasksPath - Path to tasks.json file
 * @returns {Object} Tasks metadata
 */
export function extractTasksMetadata(tasksPath) {
  if (!existsSync(tasksPath)) {
    return {
      error: 'Tasks file not found',
      path: tasksPath
    };
  }

  try {
    const content = readFileSync(tasksPath, 'utf8');
    const tasks = JSON.parse(content);

    const regularTasks = tasks.tasks?.filter(t => t.id?.startsWith('T')) || [];
    const checkpoints = tasks.tasks?.filter(t => t.id?.startsWith('CHECKPOINT')) || [];

    return {
      total: tasks.tasks?.length || 0,
      regularTasks: regularTasks.length,
      checkpoints: checkpoints.length,

      categories: tasks.categories || {},

      byStatus: {
        pending: regularTasks.filter(t => t.status === 'pending').length,
        inProgress: regularTasks.filter(t => t.status === 'in_progress').length,
        done: regularTasks.filter(t => t.status === 'done').length,
        blocked: regularTasks.filter(t => t.status === 'blocked').length
      },

      estimatedTime: regularTasks.reduce((sum, t) => sum + (t.estimatedMinutes || 0), 0),

      nextTask: regularTasks.find(t => t.status === 'pending' &&
                                   (!t.dependencies || t.dependencies.length === 0)),

      generatedAt: new Date().toISOString(),
      source: tasksPath
    };
  } catch (error) {
    return {
      error: error.message,
      path: tasksPath
    };
  }
}

/**
 * Extract comprehensive feature metadata
 * @param {Object} featureState - Feature state from state.json
 * @returns {Object} Complete feature metadata
 */
export function extractFeatureMetadata(featureState) {
  const metadata = {
    version: "1.0.0",
    feature: featureState.name || 'unknown',
    status: featureState.status,
    phase: featureState.phase,
    workflow: featureState.workflow,

    agents: featureState.activeAgents || [],
    checkpoints: featureState.checkpoints || [],

    outputs: {},
    quickLinks: {}
  };

  // Extract metadata from each output
  if (featureState.outputs?.proposal?.created) {
    metadata.outputs.proposal = extractProposalMetadata(featureState.outputs.proposal.path);
    metadata.quickLinks.proposal = featureState.outputs.proposal.path;
  }

  if (featureState.outputs?.spec?.created) {
    metadata.outputs.spec = extractSpecMetadata(featureState.outputs.spec.path);
    metadata.quickLinks.spec = featureState.outputs.spec.path;
  }

  if (featureState.outputs?.decisions?.created) {
    metadata.outputs.decisions = extractDecisionsMetadata(featureState.outputs.decisions.path);
    metadata.quickLinks.decisions = featureState.outputs.decisions.path;
  }

  if (featureState.outputs?.tasks?.created) {
    metadata.outputs.tasks = extractTasksMetadata(featureState.outputs.tasks.path);
    metadata.quickLinks.tasks = featureState.outputs.tasks.path;
  }

  // Calculate progress
  if (featureState.tasks) {
    metadata.progress = {
      total: featureState.tasks.total || 0,
      completed: featureState.tasks.completed || 0,
      percentage: featureState.tasks.total > 0
        ? Math.round((featureState.tasks.completed / featureState.tasks.total) * 100)
        : 0
    };
  }

  metadata.generatedAt = new Date().toISOString();

  return metadata;
}
