/**
 * @fileoverview Hierarchical Agent Teams Orchestrator
 *
 * Builds Agent Teams using 4-tier hierarchy:
 * - Tier 1: Orchestrators (Team Lead in delegate mode)
 * - Tier 2: Domain Leaders (Squad Leaders)
 * - Tier 3: Specialists (Domain experts)
 * - Tier 4: Validators (Run in hooks, not teammates)
 *
 * @module team-orchestrator
 */

import fs from 'fs/promises';
import path from 'path';
import { fileURLToPath } from 'url';
import { resolveAgentsConfigPath } from '../stacks/stack-resolver.js';

const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);

/**
 * Load agents.json with hierarchical structure
 * @param {string} projectPath - Root path of the project
 * @returns {Promise<Object>} Parsed agents configuration
 */
async function loadAgentsConfig(projectPath) {
  const agentsPath = resolveAgentsConfigPath(projectPath);
  const content = await fs.readFile(agentsPath, 'utf8');
  return JSON.parse(content);
}

/**
 * Detect if Agent Teams should be spawned based on complexity
 * @param {Object} options
 * @param {string[]} options.activeAgents - Agent IDs detected for feature
 * @param {string} options.complexity - Complexity level (trivial|low|medium|high|critical)
 * @param {number} options.estimatedFiles - Estimated files to modify
 * @param {boolean} options.multiDomain - Does feature span multiple domains?
 * @returns {Object} { shouldSpawn: boolean, reason: string, recommendedMode: string }
 */
export function shouldSpawnAgentTeam(options) {
  const { activeAgents = [], complexity, estimatedFiles = 0, multiDomain = false } = options;

  // Never spawn for trivial/low complexity
  if (complexity === 'trivial' || complexity === 'low') {
    return {
      shouldSpawn: false,
      reason: 'Complexity too low - single session sufficient',
      recommendedMode: 'single'
    };
  }

  // Always spawn for critical complexity
  if (complexity === 'critical') {
    return {
      shouldSpawn: true,
      reason: 'Critical complexity - parallel coordination essential',
      recommendedMode: 'tmux'
    };
  }

  // Spawn if multi-domain (backend + frontend + infra)
  if (multiDomain) {
    return {
      shouldSpawn: true,
      reason: 'Multi-domain feature - benefits from parallel squads',
      recommendedMode: 'auto'
    };
  }

  // Spawn if 3+ independent modules (high file count)
  if (estimatedFiles >= 15) {
    return {
      shouldSpawn: true,
      reason: 'High file count - parallel implementation recommended',
      recommendedMode: 'auto'
    };
  }

  // Spawn if 5+ specialists active (indicates complex coordination)
  if (activeAgents.length >= 5) {
    return {
      shouldSpawn: true,
      reason: '5+ specialists active - team coordination beneficial',
      recommendedMode: 'auto'
    };
  }

  // Default: single session for medium complexity
  return {
    shouldSpawn: false,
    reason: 'Medium complexity - single session with subagents OK',
    recommendedMode: 'single'
  };
}

/**
 * Build hierarchical team structure from active agents
 * @param {string[]} activeAgentIds - Agent IDs to include in team
 * @param {Object} agentsConfig - Loaded agents.json
 * @returns {Object} Team structure with lead, domain leaders, specialists
 */
export function buildTeamHierarchy(activeAgentIds, agentsConfig) {
  const agents = agentsConfig.agents;
  const activeAgents = activeAgentIds
    .filter(id => !id.startsWith('_comment') && agents[id])
    .map(id => ({ id, ...agents[id] }));

  // Tier 1: Orchestrator (Team Lead)
  const orchestrators = activeAgents.filter(a => a.tier === 1 && a.role === 'orchestrator');
  const teamLead = orchestrators.find(a => a.id === 'standards-architect') || orchestrators[0];

  // Tier 2: Domain Leaders
  const domainLeaders = activeAgents.filter(a => a.tier === 2 && a.role === 'domain-leader');

  // Tier 3: Specialists (group by domain)
  const specialists = activeAgents.filter(a => a.tier === 3 && a.role === 'specialist');

  // Tier 4: Validators (run in hooks, NOT teammates)
  const validators = activeAgents.filter(a => a.tier === 4 && a.role === 'validator');

  // Group specialists under their Domain Leaders
  const squads = {};
  domainLeaders.forEach(leader => {
    const squadMembers = specialists.filter(specialist => {
      // Check if specialist reports to this leader
      return specialist.relationships?.reports_to === leader.id;
    });

    if (squadMembers.length > 0) {
      squads[leader.id] = {
        leader,
        members: squadMembers
      };
    }
  });

  return {
    teamLead,
    squads,
    validators, // Not in teammates, run as hooks
    totalTeammates: 1 + domainLeaders.length + specialists.length // Lead + Leaders + Specialists
  };
}

/**
 * Generate teammate spawn instructions for Agent Teams
 * @param {Object} teamHierarchy - Output from buildTeamHierarchy
 * @param {string} featureName - Feature name
 * @param {string} phase - Current MORPH phase
 * @returns {Object[]} Array of teammate configs for Agent Teams
 */
export function generateTeammateConfigs(teamHierarchy, featureName, phase) {
  const teammates = [];
  const { teamLead, squads } = teamHierarchy;

  // Add Team Lead (standards-architect in delegate mode)
  if (teamLead && teamLead.teammate) {
    teammates.push({
      id: teamLead.id,
      tier: teamLead.tier,
      role: teamLead.teammate.role,
      icon: teamLead.teammate.icon,
      spawnPrompt: `${teamLead.teammate.spawn_prompt}

Feature: ${featureName}
Phase: ${phase}

Your Domain Leaders:
${Object.values(squads).map(s => `- ${s.leader.title} (${s.leader.id})`).join('\n')}

DO NOT implement code yourself. Coordinate Domain Leaders, resolve conflicts, synthesize results.`
    });
  }

  // Add Domain Leaders + their squad members
  Object.entries(squads).forEach(([leaderId, squad]) => {
    const leader = squad.leader;

    // Add Domain Leader
    if (leader.teammate) {
      teammates.push({
        id: leader.id,
        tier: leader.tier,
        role: leader.teammate.role,
        icon: leader.teammate.icon,
        spawnPrompt: `${leader.teammate.spawn_prompt}

Feature: ${featureName}
Phase: ${phase}

Your Squad (${squad.members.length} specialists):
${squad.members.map(m => `- ${m.title} (${m.id})`).join('\n')}

Coordinate your specialists. Escalate conflicts to ${leader.relationships.escalates_to}.`
      });
    }

    // Add Specialists in this squad
    squad.members.forEach(specialist => {
      if (specialist.teammate) {
        teammates.push({
          id: specialist.id,
          tier: specialist.tier,
          role: specialist.teammate.role,
          icon: specialist.teammate.icon,
          spawnPrompt: `${specialist.teammate.spawn_prompt}

Feature: ${featureName}
Phase: ${phase}

Reports to: ${specialist.relationships.reports_to}
Escalate to: ${specialist.relationships.escalates_to}

${specialist.relationships.collaborates_with ?
  `Collaborate with: ${specialist.relationships.collaborates_with.join(', ')}` : ''}`
        });
      }
    });
  });

  return teammates;
}

/**
 * Generate Agent Teams command for spawning
 * @param {Object[]} teammates - Output from generateTeammateConfigs
 * @param {string} displayMode - 'auto' | 'in-process' | 'tmux'
 * @returns {string} Command to spawn Agent Teams
 */
export function generateSpawnCommand(teammates, displayMode = 'auto') {
  // Agent Teams are spawned via Claude Code's Task tool with subagent_type="general-purpose"
  // and special teammate configs. This is a conceptual representation.

  const command = {
    tool: 'Task',
    subagent_type: 'general-purpose',
    agent_teams_enabled: true,
    display_mode: displayMode,
    teammates: teammates.map(t => ({
      id: t.id,
      role: t.role,
      icon: t.icon,
      prompt: t.spawnPrompt
    }))
  };

  return JSON.stringify(command, null, 2);
}

/**
 * Main orchestration function - decides if/when to spawn Agent Teams
 * @param {Object} options
 * @param {string} options.projectPath - Project root path
 * @param {string} options.featureName - Feature name
 * @param {string} options.phase - MORPH phase
 * @param {string[]} options.activeAgents - Active agent IDs
 * @param {string} options.complexity - Complexity level
 * @param {number} options.estimatedFiles - Estimated file count
 * @param {boolean} options.multiDomain - Multi-domain feature?
 * @returns {Promise<Object>} Team orchestration result
 */
export async function orchestrateTeam(options) {
  const {
    projectPath,
    featureName,
    phase,
    activeAgents = [],
    complexity,
    estimatedFiles = 0,
    multiDomain = false
  } = options;

  // Step 1: Decide if Agent Teams should spawn
  const spawnDecision = shouldSpawnAgentTeam({
    activeAgents,
    complexity,
    estimatedFiles,
    multiDomain
  });

  if (!spawnDecision.shouldSpawn) {
    return {
      useAgentTeams: false,
      reason: spawnDecision.reason,
      recommendation: 'Use single session with Task tool for subagents'
    };
  }

  // Step 2: Load agents config and build hierarchy
  const agentsConfig = await loadAgentsConfig(projectPath);
  const teamHierarchy = buildTeamHierarchy(activeAgents, agentsConfig);

  // Step 3: Generate teammate configs
  const teammates = generateTeammateConfigs(teamHierarchy, featureName, phase);

  // Step 4: Generate spawn command
  const spawnCommand = generateSpawnCommand(teammates, spawnDecision.recommendedMode);

  return {
    useAgentTeams: true,
    reason: spawnDecision.reason,
    displayMode: spawnDecision.recommendedMode,
    teamHierarchy: {
      teamLead: teamHierarchy.teamLead?.id,
      squads: Object.keys(teamHierarchy.squads),
      totalTeammates: teamHierarchy.totalTeammates,
      validators: teamHierarchy.validators.map(v => v.id)
    },
    teammates,
    spawnCommand,
    recommendation: `Spawn ${teamHierarchy.totalTeammates} teammates in ${spawnDecision.recommendedMode} mode`
  };
}

/**
 * Get agent squad assignments (for informational purposes)
 * @param {Object} agentsConfig - Loaded agents.json
 * @returns {Object} Squad information
 */
export function getSquadInfo(agentsConfig) {
  return agentsConfig.squads || {};
}
