#!/usr/bin/env bash
# compute-team: Scan team/ profiles and room/ artifacts to produce TEAM-STATE.md
# A knowledge landscape context tool for Larry -- never productivity/attendance tracking
# Called by compute-state as a sub-step
#
# Usage: scripts/compute-team <room_dir>
# Output: Writes room/team/TEAM-STATE.md directly
# Exit: 0 on success, 1 on error. If no team/ directory, exit 0 silently.

# macOS bash 3.2 compatibility -- Python3 fallback for declare -A (associative arrays)
if [ "${BASH_VERSINFO[0]:-0}" -lt 4 ]; then
  exec python3 - "$@" << 'PYEOF'
import sys, os, re, subprocess, time
from pathlib import Path
from datetime import datetime, timezone

room_dir = sys.argv[1] if len(sys.argv) > 1 else "."
team_dir = os.path.join(room_dir, "team")

if not os.path.isdir(team_dir):
    sys.exit(0)

# --- 12-type role taxonomy ---
ALL_ROLES = "mentor researcher team-member investor advisor customer founder partner domain-expert government competitor unknown".split()

# --- Scan PROFILE.md files ---
p_names = []
p_roles = []
p_primary_roles = []
p_statuses = []
p_affiliations = []
p_first_meetings = []
p_last_actives = []
p_meetings_attended = []
p_profile_paths = []

def find_profiles(base):
    result = []
    for root, dirs, files in os.walk(base):
        dirs.sort()
        for f in sorted(files):
            if f == "PROFILE.md":
                result.append(os.path.join(root, f))
    return result

def extract_frontmatter(filepath):
    lines = []
    with open(filepath, "r") as f:
        content = f.readlines()
    in_fm = False
    count = 0
    for line in content:
        stripped = line.rstrip("\n")
        if stripped == "---":
            count += 1
            if count == 1:
                in_fm = True
                continue
            if count == 2:
                break
        if in_fm:
            lines.append(stripped)
    return lines

def fm_get(fm_lines, key):
    for line in fm_lines:
        if line.startswith(key + ":"):
            return line[len(key)+1:].strip()
    return ""

profile_files = find_profiles(team_dir)

for profile_file in profile_files:
    fm = extract_frontmatter(profile_file)
    name = fm_get(fm, "name")
    if not name:
        continue

    roles_raw = fm_get(fm, "roles")
    if roles_raw:
        roles = ", ".join([r.strip().strip('"') for r in roles_raw.strip("[]").split(",") if r.strip()])
    else:
        role_single = fm_get(fm, "role")
        roles = role_single if role_single else "unknown"

    primary_role = fm_get(fm, "primary_role")
    if not primary_role:
        primary_role = fm_get(fm, "role")
    if not primary_role:
        primary_role = "unknown"

    status = fm_get(fm, "status") or "active"
    affiliation = fm_get(fm, "affiliation") or "Unknown"
    first_meeting = fm_get(fm, "first_meeting")
    last_active = fm_get(fm, "last_active")
    meetings_attended = fm_get(fm, "meetings_attended") or "0"

    profile_rel = profile_file
    if profile_rel.startswith(room_dir + "/"):
        profile_rel = profile_rel[len(room_dir)+1:]
    profile_dir_val = os.path.dirname(profile_rel)

    p_names.append(name)
    p_roles.append(roles)
    p_primary_roles.append(primary_role)
    p_statuses.append(status)
    p_affiliations.append(affiliation)
    p_first_meetings.append(first_meeting)
    p_last_actives.append(last_active)
    p_meetings_attended.append(meetings_attended)
    p_profile_paths.append(profile_dir_val)

profile_count = len(p_names)
if profile_count == 0:
    sys.exit(0)

# --- Scan room/ sections for contributions ---
contrib_counts = {}      # "name|section" -> count
person_sections = {}     # "name" -> set of sections
person_artifacts = {}    # "name" -> list of "date|section|type|filename"

section_dirs = []
for entry in sorted(os.listdir(room_dir)):
    full = os.path.join(room_dir, entry)
    if not os.path.isdir(full):
        continue
    if entry.startswith("."):
        continue
    if entry in ("team", "meetings"):
        continue
    section_dirs.append(entry)

for section_name in section_dirs:
    section_path = os.path.join(room_dir, section_name)
    for fname in sorted(os.listdir(section_path)):
        if not fname.endswith(".md"):
            continue
        md_file = os.path.join(section_path, fname)
        if not os.path.isfile(md_file):
            continue
        if fname in ("ROOM.md", "TEAM-STATE.md", "STATE.md"):
            continue

        fm = extract_frontmatter(md_file)

        # Extract speaker
        speaker = ""
        for line in fm:
            if line.startswith("  speaker:"):
                speaker = line[len("  speaker:"):].strip()
                break
        if not speaker:
            speaker = fm_get(fm, "speaker")
        if not speaker:
            continue

        seg_type = fm_get(fm, "segment_type")
        if not seg_type:
            seg_type = fm_get(fm, "type")
        if not seg_type:
            seg_type = "entry"

        art_date = ""
        for line in fm:
            if line.startswith("  meeting_date:"):
                art_date = line[len("  meeting_date:"):].strip()
                break
        if not art_date:
            art_date = fm_get(fm, "date")
        if not art_date:
            m = re.match(r'^(\d{4}-\d{2}-\d{2})', fname)
            if m:
                art_date = m.group(1)
        if not art_date:
            art_date = "unknown"

        key = "{}|{}".format(speaker, section_name)
        contrib_counts[key] = contrib_counts.get(key, 0) + 1

        if speaker not in person_sections:
            person_sections[speaker] = set()
        person_sections[speaker].add(section_name)

        if speaker not in person_artifacts:
            person_artifacts[speaker] = []
        person_artifacts[speaker].append("{}|{}|{}|{}".format(art_date, section_name, seg_type, fname))

# --- Compute expertise distribution ---
expertise_primary = []
expertise_sections = []
expertise_total = []

for i in range(len(p_names)):
    name = p_names[i]
    sections_set = person_sections.get(name, set())
    if not sections_set:
        expertise_primary.append("(no contributions)")
        expertise_sections.append("-")
        expertise_total.append("0")
        continue

    max_count = 0
    max_section = ""
    total_count = 0
    for sec in sections_set:
        key = "{}|{}".format(name, sec)
        cnt = contrib_counts.get(key, 0)
        total_count += cnt
        if cnt > max_count:
            max_count = cnt
            max_section = sec

    expertise_primary.append(max_section)
    expertise_sections.append(",".join(sorted(sections_set)))
    expertise_total.append(str(total_count))

# --- Compute knowledge gaps ---
section_contributors = {}
for key in contrib_counts:
    person, section = key.split("|", 1)
    if section not in section_contributors:
        section_contributors[section] = set()
    section_contributors[section].add(person)

# --- Compute missing perspectives ---
represented_roles = set(p_primary_roles)
missing_roles = [r for r in ALL_ROLES if r != "unknown" and r not in represented_roles]

# --- Compute role distribution ---
role_counts = {}
role_members = {}
for i in range(len(p_names)):
    pr = p_primary_roles[i]
    role_counts[pr] = role_counts.get(pr, 0) + 1
    if pr not in role_members:
        role_members[pr] = p_names[i]
    else:
        role_members[pr] = role_members[pr] + ", " + p_names[i]

# --- Compute activity patterns ---
try:
    today_epoch = int(time.time())
except:
    today_epoch = 0

def compute_trend(last_active, status):
    if not last_active or last_active == "unknown":
        return "unknown"
    try:
        from datetime import datetime as dt
        la = dt.strptime(last_active[:10], "%Y-%m-%d")
        la_epoch = int(la.timestamp())
    except:
        return "unknown"
    days_ago = (today_epoch - la_epoch) // 86400
    if days_ago <= 14:
        return "consistent"
    elif days_ago <= 30:
        return "occasional"
    elif status == "active":
        return "declining"
    else:
        return "inactive"

p_trends = [compute_trend(p_last_actives[i], p_statuses[i]) for i in range(len(p_names))]

# --- Compute counts ---
active_count = sum(1 for s in p_statuses if s == "active")

unique_roles_list = []
for pr in p_primary_roles:
    if pr not in unique_roles_list:
        unique_roles_list.append(pr)
unique_roles = ", ".join(unique_roles_list)

# --- Write TEAM-STATE.md ---
timestamp = datetime.now(timezone.utc).strftime("%Y-%m-%dT%H:%M:%SZ")
output_file = os.path.join(team_dir, "TEAM-STATE.md")

with open(output_file, "w") as f:
    f.write("---\n")
    f.write("computed: {}\n".format(timestamp))
    f.write("team_size: {}\n".format(profile_count))
    f.write("active_members: {}\n".format(active_count))
    f.write("roles_represented: [{}]\n".format(unique_roles))
    f.write("---\n")
    f.write("# Team Knowledge Landscape\n\n")

    # Expertise Distribution
    f.write("## Expertise Distribution\n\n")
    f.write("| Person | Primary Expertise | Sections Contributed | Last Active |\n")
    f.write("|--------|------------------|---------------------|-------------|\n")
    for i in range(len(p_names)):
        sections_display = expertise_sections[i]
        if sections_display == "-":
            sections_display = "(none)"
        la = p_last_actives[i] if p_last_actives[i] else "unknown"
        f.write("| {} | {} | {} | {} |\n".format(p_names[i], expertise_primary[i], sections_display, la))
    f.write("\n")

    # Knowledge Gaps
    f.write("## Knowledge Gaps\n\n")
    f.write("| Section | Contributors | Gap Assessment |\n")
    f.write("|---------|-------------|----------------|\n")
    for section_name in section_dirs:
        contributors = section_contributors.get(section_name, set())
        if not contributors:
            f.write("| {} | 0 | CRITICAL: No perspectives filed |\n".format(section_name))
        elif len(contributors) == 1:
            person = list(contributors)[0]
            f.write("| {} | 1 ({}) | CONCENTRATION: Single perspective only |\n".format(section_name, person))
        else:
            f.write("| {} | {} | Diverse -- {} perspectives |\n".format(section_name, len(contributors), len(contributors)))
    f.write("\n")

    # Missing Perspectives
    f.write("## Missing Perspectives\n\n")
    if not missing_roles:
        f.write("All role types from the 12-type taxonomy are represented.\n")
    else:
        role_messages = {
            "customer": '- CRITICAL: No **customer** voice on the team. Customer perspective is the most commonly missing in early ventures.',
            "domain-expert": '- CRITICAL: No **domain-expert** perspective. Deep domain knowledge reduces false assumptions.',
            "investor": '- No **investor** perspective. Consider before fundraising conversations.',
            "mentor": '- No **mentor** perspective. Experienced guidance accelerates learning cycles.',
            "researcher": '- No **researcher** perspective. Research grounds decisions in evidence.',
            "advisor": '- No **advisor** perspective. Strategic advisors expand the network.',
            "government": '- No **government/regulatory** perspective. Relevant for regulated markets.',
            "founder": '- No **founder** on team. Core leadership role not yet represented.',
            "partner": '- No **partner** perspective. Partnerships can unlock distribution.',
            "team-member": '- No **team-member** roles. Core execution capacity not represented.',
            "competitor": '- No **competitor** intelligence. Understanding competition sharpens positioning.',
        }
        for role in missing_roles:
            f.write(role_messages.get(role, "- No **{}** perspective represented.".format(role)) + "\n")
    f.write("\n")

    # Role Distribution
    f.write("## Role Distribution\n\n")
    f.write("| Role | Count | Members |\n")
    f.write("|------|-------|--------|\n")
    for role in ALL_ROLES:
        cnt = role_counts.get(role, 0)
        if cnt == 0:
            continue
        members = role_members.get(role, "")
        f.write("| {} | {} | {} |\n".format(role, cnt, members))
    f.write("\n")

    # Activity Patterns
    f.write("## Activity Patterns\n\n")
    f.write("| Person | Status | Meetings | Last Active | Trend |\n")
    f.write("|--------|--------|----------|-------------|-------|\n")
    for i in range(len(p_names)):
        la = p_last_actives[i] if p_last_actives[i] else "unknown"
        f.write("| {} | {} | {} | {} | {} |\n".format(
            p_names[i], p_statuses[i], p_meetings_attended[i], la, p_trends[i]))
    f.write("\n")

    # Recurring Concerns
    f.write("## Recurring Concerns\n\n")
    person_topic_counts = {}
    person_topic_first = {}

    for name, artifacts_list in person_artifacts.items():
        section_counts_local = {}
        section_first_local = {}
        for art_line in artifacts_list:
            parts = art_line.split("|")
            if len(parts) < 2:
                continue
            art_date = parts[0]
            art_section = parts[1]
            if not art_section:
                continue
            section_counts_local[art_section] = section_counts_local.get(art_section, 0) + 1
            first = section_first_local.get(art_section)
            if first is None or art_date < first:
                section_first_local[art_section] = art_date

        for sec, cnt in section_counts_local.items():
            key = "{}|{}".format(name, sec)
            person_topic_counts[key] = cnt
            person_topic_first[key] = section_first_local[sec]

    recurring_lines = []
    for key, cnt in person_topic_counts.items():
        if cnt >= 3:
            person, topic = key.split("|", 1)
            first_date = person_topic_first[key]
            recurring_lines.append("| {} | {} | {} | {} |".format(person, topic, cnt, first_date))

    if recurring_lines:
        f.write("| Person | Concern | Frequency | First Raised |\n")
        f.write("|--------|---------|-----------|-------------|\n")
        for line in recurring_lines:
            f.write(line + "\n")
    else:
        f.write("No recurring concerns detected yet. Requires 3+ artifacts from the same person in the same section.\n")
    f.write("\n")

    # Influence Distribution
    f.write("## Influence Distribution\n\n")
    person_decisions = {}
    person_insights = {}
    person_domain_decisions = {}

    for name, artifacts_list in person_artifacts.items():
        d_count = 0
        i_count = 0
        for art_line in artifacts_list:
            parts = art_line.split("|")
            if len(parts) < 3:
                continue
            art_section = parts[1]
            art_type = parts[2]
            if not art_type:
                continue
            if art_type == "decision":
                d_count += 1
                dd_key = "{}|{}".format(art_section, name)
                person_domain_decisions[dd_key] = person_domain_decisions.get(dd_key, 0) + 1
            elif art_type == "insight":
                i_count += 1
        person_decisions[name] = d_count
        person_insights[name] = i_count

    # Find primary voice per domain
    domain_primary_voice = {}
    domain_primary_count = {}

    for key, cnt in person_domain_decisions.items():
        section, name = key.split("|", 1)
        current_max = domain_primary_count.get(section, 0)
        if cnt > current_max:
            domain_primary_voice[section] = name
            domain_primary_count[section] = cnt

    if domain_primary_voice:
        f.write("| Domain | Primary Voice | Decisions Led |\n")
        f.write("|--------|--------------|---------------|\n")
        for section in domain_primary_voice:
            f.write("| {} | {} | {} |\n".format(section, domain_primary_voice[section], domain_primary_count[section]))
    else:
        f.write("No decision artifacts attributed yet.\n")
    f.write("\n")

    # Influence scores
    influence_lines = []
    for name in person_decisions:
        d = person_decisions[name]
        ins = person_insights.get(name, 0)
        score_x2 = d * 2 + ins
        score_int = score_x2 // 2
        score_dec = score_x2 % 2
        if d > 0 or ins > 0:
            influence_lines.append("| {} | {} | {} | {}.{} |".format(name, d, ins, score_int, score_dec))

    if influence_lines:
        f.write("### Influence Scores\n\n")
        f.write("| Person | Decisions | Insights | Influence Score |\n")
        f.write("|--------|-----------|----------|----------------|\n")
        for line in influence_lines:
            f.write(line + "\n")

# --- Update PROFILE.md Contributions sections ---
for i in range(len(p_names)):
    name = p_names[i]
    profile_dir_val = p_profile_paths[i]
    profile_file = os.path.join(room_dir, profile_dir_val, "PROFILE.md")

    if not os.path.isfile(profile_file):
        continue

    artifacts_list = person_artifacts.get(name, [])

    contrib_table = "## Contributions\n\n"
    if not artifacts_list:
        contrib_table += "[No contributions found yet]\n"
    else:
        contrib_table += "| Date | Section | Type | Artifact |\n"
        contrib_table += "|------|---------|------|----------|\n"
        sorted_arts = sorted(artifacts_list, key=lambda x: x.split("|")[0], reverse=True)
        for art_line in sorted_arts:
            parts = art_line.split("|")
            if len(parts) < 4 or not parts[3]:
                continue
            contrib_table += "| {} | {} | {} | [[{}/{}]] |\n".format(parts[0], parts[1], parts[2], parts[1], parts[3])

    with open(profile_file, "r") as pf:
        content = pf.read()

    if re.search(r'^## (Key )?Contributions', content, re.MULTILINE):
        # Replace the section
        lines = content.split("\n")
        new_lines = []
        in_section = False
        for line in lines:
            if re.match(r'^## (Key )?Contributions', line):
                new_lines.append(contrib_table.rstrip("\n"))
                in_section = True
                continue
            if in_section and line.startswith("## "):
                in_section = False
            if not in_section:
                new_lines.append(line)
        with open(profile_file, "w") as pf:
            pf.write("\n".join(new_lines))

sys.exit(0)
PYEOF
fi

set -e

# Portable date -d replacement (macOS lacks GNU date -d)
portable_date_to_epoch() {
  local datestr="$1"
  date -d "$datestr" +%s 2>/dev/null \
    || date -j -f "%Y-%m-%d" "$datestr" +%s 2>/dev/null \
    || python3 -c "from datetime import datetime; print(int(datetime.strptime('$datestr','%Y-%m-%d').timestamp()))" 2>/dev/null \
    || echo "0"
}

ROOM_DIR="${1:-.}"
TEAM_DIR="$ROOM_DIR/team"

# No team directory = no team yet, exit silently
if [[ ! -d "$TEAM_DIR" ]]; then
  exit 0
fi

# ─── 12-type role taxonomy ───────────────────────────────────────────────────
ALL_ROLES="mentor researcher team-member investor advisor customer founder partner domain-expert government competitor unknown"

# ─── Scan PROFILE.md files ───────────────────────────────────────────────────
declare -a p_names=()
declare -a p_roles=()
declare -a p_primary_roles=()
declare -a p_statuses=()
declare -a p_affiliations=()
declare -a p_first_meetings=()
declare -a p_last_actives=()
declare -a p_meetings_attended=()
declare -a p_profile_paths=()

profile_count=0

while IFS= read -r profile_file; do
  [ -f "$profile_file" ] || continue

  # Extract fields from frontmatter (between first two --- lines)
  frontmatter=$(sed -n '/^---$/,/^---$/p' "$profile_file" | head -50)

  name=$(echo "$frontmatter" | grep '^name:' | head -1 | sed 's/^name: *//')
  [ -z "$name" ] && continue

  # Resolve roles: try roles: list first, fall back to role: singular
  roles_raw=$(echo "$frontmatter" | grep '^roles:' | head -1 | sed 's/^roles: *//')
  if [ -n "$roles_raw" ]; then
    # Parse [mentor, advisor] or - mentor format
    roles=$(echo "$roles_raw" | tr -d '[]' | tr ',' '\n' | sed 's/^ *//;s/ *$//' | grep -v '^$' | tr '\n' ', ' | sed 's/,$//' | sed 's/, *$//')
  else
    role_single=$(echo "$frontmatter" | grep '^role:' | head -1 | sed 's/^role: *//')
    roles="${role_single:-unknown}"
  fi

  # Primary role: try primary_role first, fall back to role, fall back to first in roles
  primary_role=$(echo "$frontmatter" | grep '^primary_role:' | head -1 | sed 's/^primary_role: *//')
  if [ -z "$primary_role" ]; then
    primary_role=$(echo "$frontmatter" | grep '^role:' | head -1 | sed 's/^role: *//')
  fi
  [ -z "$primary_role" ] && primary_role="unknown"

  status=$(echo "$frontmatter" | grep '^status:' | head -1 | sed 's/^status: *//')
  [ -z "$status" ] && status="active"

  affiliation=$(echo "$frontmatter" | grep '^affiliation:' | head -1 | sed 's/^affiliation: *//')
  [ -z "$affiliation" ] && affiliation="Unknown"

  first_meeting=$(echo "$frontmatter" | grep '^first_meeting:' | head -1 | sed 's/^first_meeting: *//')
  last_active=$(echo "$frontmatter" | grep '^last_active:' | head -1 | sed 's/^last_active: *//')
  meetings_attended=$(echo "$frontmatter" | grep '^meetings_attended:' | head -1 | sed 's/^meetings_attended: *//')
  [ -z "$meetings_attended" ] && meetings_attended="0"

  # Store profile path relative to room
  profile_rel=$(echo "$profile_file" | sed "s|^$ROOM_DIR/||")
  profile_dir=$(dirname "$profile_rel")

  p_names+=("$name")
  p_roles+=("$roles")
  p_primary_roles+=("$primary_role")
  p_statuses+=("$status")
  p_affiliations+=("$affiliation")
  p_first_meetings+=("$first_meeting")
  p_last_actives+=("$last_active")
  p_meetings_attended+=("$meetings_attended")
  p_profile_paths+=("$profile_dir")

  profile_count=$((profile_count + 1))
done < <(find "$TEAM_DIR" -name "PROFILE.md" -type f 2>/dev/null | sort)

# If no profiles found, exit silently
if [ "$profile_count" -eq 0 ]; then
  exit 0
fi

# ─── Scan room/ sections for contributions ───────────────────────────────────
# Build associative arrays: person -> section -> count, person -> artifacts list
declare -A contrib_counts      # "name|section" -> count
declare -A person_sections     # "name" -> "section1,section2,..."
declare -A person_artifacts    # "name" -> "date|section|type|filename\n..."

# Collect section directories (skip team/, meetings/, hidden dirs)
section_dirs=()
for section_dir in "$ROOM_DIR"/*/; do
  [ -d "$section_dir" ] || continue
  section_name=$(basename "$section_dir")
  [[ "$section_name" == .* ]] && continue
  [[ "$section_name" == "team" ]] && continue
  [[ "$section_name" == "meetings" ]] && continue
  section_dirs+=("$section_name")
done

for section_name in "${section_dirs[@]}"; do
  section_path="$ROOM_DIR/$section_name"
  for md_file in "$section_path"/*.md; do
    [ -f "$md_file" ] || continue
    fname=$(basename "$md_file")
    [ "$fname" = "ROOM.md" ] && continue
    [ "$fname" = "TEAM-STATE.md" ] && continue
    [ "$fname" = "STATE.md" ] && continue

    # Extract speaker: try nested attribution block first, fall back to flat
    frontmatter=$(sed -n '/^---$/,/^---$/p' "$md_file" | head -50)

    speaker=""
    # Try nested attribution: look for "  speaker:" (indented)
    speaker=$(echo "$frontmatter" | grep '^  speaker:' | head -1 | sed 's/^  speaker: *//')
    # Fall back to flat speaker: field
    if [ -z "$speaker" ]; then
      speaker=$(echo "$frontmatter" | grep '^speaker:' | head -1 | sed 's/^speaker: *//')
    fi

    [ -z "$speaker" ] && continue

    # Extract segment_type and date
    seg_type=$(echo "$frontmatter" | grep '^segment_type:' | head -1 | sed 's/^segment_type: *//')
    [ -z "$seg_type" ] && seg_type=$(echo "$frontmatter" | grep '^type:' | head -1 | sed 's/^type: *//')
    [ -z "$seg_type" ] && seg_type="entry"

    # Extract date from attribution block or flat field or filename
    art_date=$(echo "$frontmatter" | grep '^  meeting_date:' | head -1 | sed 's/^  meeting_date: *//')
    if [ -z "$art_date" ]; then
      art_date=$(echo "$frontmatter" | grep '^date:' | head -1 | sed 's/^date: *//')
    fi
    if [ -z "$art_date" ]; then
      # Try to extract date from filename (YYYY-MM-DD-*)
      art_date=$(echo "$fname" | grep -oE '^[0-9]{4}-[0-9]{2}-[0-9]{2}' || true)
    fi
    [ -z "$art_date" ] && art_date="unknown"

    # Update contribution counts
    key="${speaker}|${section_name}"
    current=${contrib_counts[$key]:-0}
    contrib_counts[$key]=$((current + 1))

    # Track which sections this person has contributed to
    existing_sections=${person_sections[$speaker]:-}
    if [[ ! ",$existing_sections," == *",$section_name,"* ]]; then
      if [ -z "$existing_sections" ]; then
        person_sections[$speaker]="$section_name"
      else
        person_sections[$speaker]="$existing_sections,$section_name"
      fi
    fi

    # Track artifacts for PROFILE.md update
    existing_artifacts=${person_artifacts[$speaker]:-}
    person_artifacts[$speaker]="${existing_artifacts}${art_date}|${section_name}|${seg_type}|${fname}
"
  done
done

# ─── Compute expertise distribution ──────────────────────────────────────────
declare -a expertise_primary=()
declare -a expertise_sections=()
declare -a expertise_total=()

for i in "${!p_names[@]}"; do
  name="${p_names[$i]}"
  sections_str=${person_sections[$name]:-}

  if [ -z "$sections_str" ]; then
    expertise_primary+=("(no contributions)")
    expertise_sections+=("-")
    expertise_total+=("0")
    continue
  fi

  # Find section with most contributions
  max_count=0
  max_section=""
  total_count=0
  IFS=',' read -ra secs <<< "$sections_str"
  for sec in "${secs[@]}"; do
    key="${name}|${sec}"
    cnt=${contrib_counts[$key]:-0}
    total_count=$((total_count + cnt))
    if [ "$cnt" -gt "$max_count" ]; then
      max_count=$cnt
      max_section=$sec
    fi
  done

  expertise_primary+=("$max_section")
  expertise_sections+=("$sections_str")
  expertise_total+=("$total_count")
done

# ─── Compute knowledge gaps ──────────────────────────────────────────────────
# For each topic section, count unique contributors
declare -A section_contributors  # section -> "name1,name2,..."

for key in "${!contrib_counts[@]}"; do
  IFS='|' read -r person section <<< "$key"
  existing=${section_contributors[$section]:-}
  if [[ ! ",$existing," == *",$person,"* ]]; then
    if [ -z "$existing" ]; then
      section_contributors[$section]="$person"
    else
      section_contributors[$section]="$existing,$person"
    fi
  fi
done

# ─── Compute missing perspectives ────────────────────────────────────────────
declare -A represented_roles
for i in "${!p_primary_roles[@]}"; do
  represented_roles[${p_primary_roles[$i]}]=1
done

missing_roles=()
for role in $ALL_ROLES; do
  [ "$role" = "unknown" ] && continue
  if [ -z "${represented_roles[$role]:-}" ]; then
    missing_roles+=("$role")
  fi
done

# ─── Compute role distribution ────────────────────────────────────────────────
declare -A role_counts
declare -A role_members

for i in "${!p_names[@]}"; do
  pr="${p_primary_roles[$i]}"
  current=${role_counts[$pr]:-0}
  role_counts[$pr]=$((current + 1))
  existing=${role_members[$pr]:-}
  if [ -z "$existing" ]; then
    role_members[$pr]="${p_names[$i]}"
  else
    role_members[$pr]="$existing, ${p_names[$i]}"
  fi
done

# ─── Compute activity patterns ───────────────────────────────────────────────
today_epoch=$(date +%s 2>/dev/null || echo "0")

compute_trend() {
  local last_active="$1"
  local status="$2"

  if [ -z "$last_active" ] || [ "$last_active" = "unknown" ]; then
    echo "unknown"
    return
  fi

  local la_epoch
  la_epoch=$(portable_date_to_epoch "$last_active")
  if [ "$la_epoch" -eq 0 ]; then
    echo "unknown"
    return
  fi

  local days_ago=$(( (today_epoch - la_epoch) / 86400 ))

  if [ "$days_ago" -le 14 ]; then
    echo "consistent"
  elif [ "$days_ago" -le 30 ]; then
    echo "occasional"
  elif [ "$status" = "active" ]; then
    echo "declining"
  else
    echo "inactive"
  fi
}

declare -a p_trends=()
for i in "${!p_names[@]}"; do
  trend=$(compute_trend "${p_last_actives[$i]}" "${p_statuses[$i]}")
  p_trends+=("$trend")
done

# ─── Compute counts ──────────────────────────────────────────────────────────
active_count=0
for i in "${!p_statuses[@]}"; do
  [ "${p_statuses[$i]}" = "active" ] && active_count=$((active_count + 1))
done

unique_roles=""
for i in "${!p_primary_roles[@]}"; do
  pr="${p_primary_roles[$i]}"
  if [[ ! ",$unique_roles," == *",$pr,"* ]]; then
    if [ -z "$unique_roles" ]; then
      unique_roles="$pr"
    else
      unique_roles="$unique_roles, $pr"
    fi
  fi
done

# ─── Write TEAM-STATE.md ─────────────────────────────────────────────────────
timestamp=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
OUTPUT_FILE="$TEAM_DIR/TEAM-STATE.md"

{
  echo "---"
  echo "computed: $timestamp"
  echo "team_size: $profile_count"
  echo "active_members: $active_count"
  echo "roles_represented: [$unique_roles]"
  echo "---"
  echo "# Team Knowledge Landscape"
  echo ""

  # Expertise Distribution
  echo "## Expertise Distribution"
  echo ""
  echo "| Person | Primary Expertise | Sections Contributed | Last Active |"
  echo "|--------|------------------|---------------------|-------------|"
  for i in "${!p_names[@]}"; do
    sections_display="${expertise_sections[$i]}"
    [ "$sections_display" = "-" ] && sections_display="(none)"
    echo "| ${p_names[$i]} | ${expertise_primary[$i]} | ${sections_display} | ${p_last_actives[$i]:-unknown} |"
  done
  echo ""

  # Knowledge Gaps
  echo "## Knowledge Gaps"
  echo ""
  echo "| Section | Contributors | Gap Assessment |"
  echo "|---------|-------------|----------------|"
  for section_name in "${section_dirs[@]}"; do
    contributors=${section_contributors[$section_name]:-}
    if [ -z "$contributors" ]; then
      contributor_count=0
      echo "| $section_name | 0 | CRITICAL: No perspectives filed |"
    else
      IFS=',' read -ra contrib_arr <<< "$contributors"
      contributor_count=${#contrib_arr[@]}
      if [ "$contributor_count" -eq 1 ]; then
        echo "| $section_name | 1 ($contributors) | CONCENTRATION: Single perspective only |"
      else
        echo "| $section_name | $contributor_count | Diverse -- $contributor_count perspectives |"
      fi
    fi
  done
  echo ""

  # Missing Perspectives
  echo "## Missing Perspectives"
  echo ""
  if [ ${#missing_roles[@]} -eq 0 ]; then
    echo "All role types from the 12-type taxonomy are represented."
  else
    for role in "${missing_roles[@]}"; do
      case "$role" in
        customer) echo "- CRITICAL: No **customer** voice on the team. Customer perspective is the most commonly missing in early ventures." ;;
        domain-expert) echo "- CRITICAL: No **domain-expert** perspective. Deep domain knowledge reduces false assumptions." ;;
        investor) echo "- No **investor** perspective. Consider before fundraising conversations." ;;
        mentor) echo "- No **mentor** perspective. Experienced guidance accelerates learning cycles." ;;
        researcher) echo "- No **researcher** perspective. Research grounds decisions in evidence." ;;
        advisor) echo "- No **advisor** perspective. Strategic advisors expand the network." ;;
        government) echo "- No **government/regulatory** perspective. Relevant for regulated markets." ;;
        founder) echo "- No **founder** on team. Core leadership role not yet represented." ;;
        partner) echo "- No **partner** perspective. Partnerships can unlock distribution." ;;
        team-member) echo "- No **team-member** roles. Core execution capacity not represented." ;;
        competitor) echo "- No **competitor** intelligence. Understanding competition sharpens positioning." ;;
        *) echo "- No **$role** perspective represented." ;;
      esac
    done
  fi
  echo ""

  # Role Distribution
  echo "## Role Distribution"
  echo ""
  echo "| Role | Count | Members |"
  echo "|------|-------|---------|"
  for role in $ALL_ROLES; do
    cnt=${role_counts[$role]:-0}
    [ "$cnt" -eq 0 ] && continue
    members=${role_members[$role]:-}
    echo "| $role | $cnt | $members |"
  done
  echo ""

  # Activity Patterns
  echo "## Activity Patterns"
  echo ""
  echo "| Person | Status | Meetings | Last Active | Trend |"
  echo "|--------|--------|----------|-------------|-------|"
  for i in "${!p_names[@]}"; do
    echo "| ${p_names[$i]} | ${p_statuses[$i]} | ${p_meetings_attended[$i]} | ${p_last_actives[$i]:-unknown} | ${p_trends[$i]} |"
  done
  echo ""

  # ─── Recurring Concerns ──────────────────────────────────────────────────
  # For each person, group their artifacts by section keywords to find recurring themes
  echo "## Recurring Concerns"
  echo ""

  has_recurring=false
  declare -A person_topic_counts    # "name|topic" -> count
  declare -A person_topic_first     # "name|topic" -> first date

  for name in "${!person_artifacts[@]}"; do
    artifacts_raw="${person_artifacts[$name]}"
    [ -z "$artifacts_raw" ] && continue

    # Count how many artifacts per section per person
    declare -A section_counts_local
    declare -A section_first_local

    while IFS='|' read -r art_date art_section art_type art_fname; do
      [ -z "$art_section" ] && continue
      key="$art_section"
      current=${section_counts_local[$key]:-0}
      section_counts_local[$key]=$((current + 1))

      first=${section_first_local[$key]:-}
      if [ -z "$first" ] || [[ "$art_date" < "$first" ]]; then
        section_first_local[$key]="$art_date"
      fi
    done <<< "$artifacts_raw"

    for sec in "${!section_counts_local[@]}"; do
      cnt="${section_counts_local[$sec]}"
      person_topic_counts["${name}|${sec}"]="$cnt"
      person_topic_first["${name}|${sec}"]="${section_first_local[$sec]}"
    done

    unset section_counts_local
    unset section_first_local
    declare -A section_counts_local
    declare -A section_first_local
  done

  # Output recurring concerns (3+ artifacts in same section)
  recurring_lines=()
  for key in "${!person_topic_counts[@]}"; do
    cnt="${person_topic_counts[$key]}"
    if [ "$cnt" -ge 3 ]; then
      IFS='|' read -r person topic <<< "$key"
      first_date="${person_topic_first[$key]}"
      recurring_lines+=("| $person | $topic | $cnt | $first_date |")
      has_recurring=true
    fi
  done

  if $has_recurring; then
    echo "| Person | Concern | Frequency | First Raised |"
    echo "|--------|---------|-----------|--------------|"
    for line in "${recurring_lines[@]}"; do
      echo "$line"
    done
  else
    echo "No recurring concerns detected yet. Requires 3+ artifacts from the same person in the same section."
  fi
  echo ""

  # ─── Influence Distribution ──────────────────────────────────────────────
  # For each person, count decision artifacts and compute influence score
  echo "## Influence Distribution"
  echo ""

  declare -A person_decisions     # name -> decision count
  declare -A person_insights      # name -> insight count
  declare -A person_domain_decisions  # "section" -> "name1:count1,name2:count2"

  for name in "${!person_artifacts[@]}"; do
    artifacts_raw="${person_artifacts[$name]}"
    [ -z "$artifacts_raw" ] && continue

    d_count=0
    i_count=0

    while IFS='|' read -r art_date art_section art_type art_fname; do
      [ -z "$art_type" ] && continue
      if [[ "$art_type" == "decision" ]]; then
        d_count=$((d_count + 1))

        # Track domain decisions
        existing=${person_domain_decisions[$art_section]:-}
        # Simple: just track who has most decisions per section
        person_domain_decisions["${art_section}|${name}"]=$((${person_domain_decisions["${art_section}|${name}"]:-0} + 1))
      elif [[ "$art_type" == "insight" ]]; then
        i_count=$((i_count + 1))
      fi
    done <<< "$artifacts_raw"

    person_decisions[$name]=$d_count
    person_insights[$name]=$i_count
  done

  # Find primary voice per domain (section with most decisions)
  declare -A domain_primary_voice   # section -> name
  declare -A domain_primary_count   # section -> count

  for key in "${!person_domain_decisions[@]}"; do
    IFS='|' read -r section name <<< "$key"
    cnt="${person_domain_decisions[$key]}"
    current_max=${domain_primary_count[$section]:-0}
    if [ "$cnt" -gt "$current_max" ]; then
      domain_primary_voice[$section]="$name"
      domain_primary_count[$section]="$cnt"
    fi
  done

  if [ ${#domain_primary_voice[@]} -gt 0 ]; then
    echo "| Domain | Primary Voice | Decisions Led |"
    echo "|--------|--------------|---------------|"
    for section in "${!domain_primary_voice[@]}"; do
      echo "| $section | ${domain_primary_voice[$section]} | ${domain_primary_count[$section]} |"
    done
  else
    echo "No decision artifacts attributed yet."
  fi
  echo ""

  # Influence scores
  has_influence=false
  influence_lines=()
  for name in "${!person_decisions[@]}"; do
    d=${person_decisions[$name]}
    ins=${person_insights[$name]:-0}
    # influence = decisions + (insights * 0.5) -- use integer math: decisions*2 + insights / 2
    score_x2=$((d * 2 + ins))
    score_int=$((score_x2 / 2))
    score_dec=$((score_x2 % 2))
    if [ "$d" -gt 0 ] || [ "$ins" -gt 0 ]; then
      influence_lines+=("| $name | $d | $ins | ${score_int}.${score_dec} |")
      has_influence=true
    fi
  done

  if $has_influence; then
    echo "### Influence Scores"
    echo ""
    echo "| Person | Decisions | Insights | Influence Score |"
    echo "|--------|-----------|----------|-----------------|"
    for line in "${influence_lines[@]}"; do
      echo "$line"
    done
  fi
} > "$OUTPUT_FILE"

# ─── Update PROFILE.md Contributions sections ────────────────────────────────
for i in "${!p_names[@]}"; do
  name="${p_names[$i]}"
  profile_dir="${p_profile_paths[$i]}"
  profile_file="$ROOM_DIR/$profile_dir/PROFILE.md"

  [ -f "$profile_file" ] || continue

  artifacts_raw=${person_artifacts[$name]:-}

  # Build contributions table
  contrib_table="## Contributions\n\n"
  if [ -z "$artifacts_raw" ]; then
    contrib_table="${contrib_table}[No contributions found yet]\n"
  else
    contrib_table="${contrib_table}| Date | Section | Type | Artifact |\n"
    contrib_table="${contrib_table}|------|---------|------|----------|\n"
    # Sort artifacts by date descending
    sorted=$(echo -n "$artifacts_raw" | sort -t'|' -k1 -r)
    while IFS='|' read -r art_date art_section art_type art_fname; do
      [ -z "$art_fname" ] && continue
      contrib_table="${contrib_table}| $art_date | $art_section | $art_type | [[$art_section/$art_fname]] |\n"
    done <<< "$sorted"
  fi

  # Replace the Contributions section in PROFILE.md
  # Find ## Contributions or ## Key Contributions, replace to next ## or EOF
  if grep -q '^## Contributions' "$profile_file" || grep -q '^## Key Contributions' "$profile_file"; then
    # Use awk to replace the section
    awk -v new_section="$(echo -e "$contrib_table")" '
      /^## Contributions/ || /^## Key Contributions/ {
        print new_section
        in_section = 1
        next
      }
      in_section && /^## / {
        in_section = 0
      }
      !in_section { print }
    ' "$profile_file" > "${profile_file}.tmp" && mv "${profile_file}.tmp" "$profile_file"
  fi
done

exit 0
