export type VisionMeetingRoute = "discussing" | "researching" | "planning";

export interface VisionAlignmentMeetingRecord {
  trigger: string;
  pm: string;
  userAdvocate: string;
  customerPanel: string;
  business: string;
  researcher: string;
  deliveryLead: string;
  partner: string;
  combatant: string;
  architect: string;
  moderator: string;
  weightedSynthesis: string;
  confidenceByArea: string;
  recommendedRoute: VisionMeetingRoute;
}

export interface MilestonePlanQualityCheck {
  issues: string[];
}

const PLACEHOLDER_VALUES = new Set([
  "",
  "not provided.",
  "missing vision alignment meeting.",
  "missing weighted synthesis.",
  "missing confidence by area.",
]);

function isMeaningful(value: string | null | undefined): boolean {
  const normalized = (value ?? "").trim().toLowerCase();
  return normalized.length > 0 && !PLACEHOLDER_VALUES.has(normalized);
}

function extractSection(content: string, heading: string): string {
  const lines = content.split("\n");
  const start = lines.findIndex((line) => line.trim() === `## ${heading}`);
  if (start === -1) return "";

  let end = lines.length;
  for (let index = start + 1; index < lines.length; index += 1) {
    if (/^##\s+/.test(lines[index])) {
      end = index;
      break;
    }
  }

  return lines.slice(start + 1, end).join("\n").trim();
}

function extractSubsection(content: string, heading: string): string {
  const lines = content.split("\n");
  const start = lines.findIndex((line) => line.trim() === `### ${heading}`);
  if (start === -1) return "";

  let end = lines.length;
  for (let index = start + 1; index < lines.length; index += 1) {
    if (/^###\s+/.test(lines[index]) || /^##\s+/.test(lines[index])) {
      end = index;
      break;
    }
  }

  return lines.slice(start + 1, end).join("\n").trim();
}

export function hasStructuredVisionAlignmentMeeting(
  meeting: Partial<VisionAlignmentMeetingRecord> | null | undefined,
): meeting is VisionAlignmentMeetingRecord {
  if (!meeting) return false;
  const route = meeting.recommendedRoute;
  return isMeaningful(meeting.trigger)
    && isMeaningful(meeting.pm)
    && isMeaningful(meeting.userAdvocate)
    && isMeaningful(meeting.customerPanel)
    && isMeaningful(meeting.business)
    && isMeaningful(meeting.researcher)
    && isMeaningful(meeting.deliveryLead)
    && isMeaningful(meeting.partner)
    && isMeaningful(meeting.combatant)
    && isMeaningful(meeting.architect)
    && isMeaningful(meeting.moderator)
    && isMeaningful(meeting.weightedSynthesis)
    && isMeaningful(meeting.confidenceByArea)
    && (route === "discussing" || route === "researching" || route === "planning");
}

export function getVisionAlignmentBlockingIssue(
  meeting: Partial<VisionAlignmentMeetingRecord> | null | undefined,
): string | null {
  if (!meeting) return "missing vision alignment meeting";
  if (!isMeaningful(meeting.trigger)) return "missing vision meeting trigger";
  if (!isMeaningful(meeting.pm)) return "missing vision meeting pm view";
  if (!isMeaningful(meeting.userAdvocate)) return "missing vision meeting user advocate view";
  if (!isMeaningful(meeting.customerPanel)) return "missing vision meeting customer panel view";
  if (!isMeaningful(meeting.business)) return "missing vision meeting business view";
  if (!isMeaningful(meeting.researcher)) return "missing vision meeting researcher view";
  if (!isMeaningful(meeting.deliveryLead)) return "missing vision meeting delivery lead view";
  if (!isMeaningful(meeting.partner)) return "missing vision meeting partner view";
  if (!isMeaningful(meeting.combatant)) return "missing vision meeting combatant view";
  if (!isMeaningful(meeting.architect)) return "missing vision meeting architect view";
  if (!isMeaningful(meeting.moderator)) return "missing vision meeting moderator decision";
  if (!isMeaningful(meeting.weightedSynthesis)) return "missing weighted synthesis";
  if (!isMeaningful(meeting.confidenceByArea)) return "missing confidence by area";
  if (meeting.recommendedRoute && meeting.recommendedRoute !== "planning") {
    return `vision meeting routed back to ${meeting.recommendedRoute}`;
  }
  if (
    meeting.recommendedRoute !== "planning"
    && meeting.recommendedRoute !== "researching"
    && meeting.recommendedRoute !== "discussing"
  ) {
    return "invalid vision meeting route";
  }
  return null;
}

export function inspectMilestoneRoadmapMarkdown(content: string): MilestonePlanQualityCheck {
  const issues: string[] = [];
  const meetingSection = extractSection(content, "Vision Alignment Meeting");
  if (!meetingSection) {
    issues.push("missing vision alignment meeting");
    return { issues };
  }

  const meeting: Partial<VisionAlignmentMeetingRecord> = {
    trigger: extractSubsection(meetingSection, "Trigger"),
    pm: extractSubsection(meetingSection, "Product Manager"),
    userAdvocate: extractSubsection(meetingSection, "User Advocate"),
    customerPanel: extractSubsection(meetingSection, "Customer Panel"),
    business: extractSubsection(meetingSection, "Business"),
    researcher: extractSubsection(meetingSection, "Researcher"),
    deliveryLead: extractSubsection(meetingSection, "Delivery Lead"),
    partner: extractSubsection(meetingSection, "Partner"),
    combatant: extractSubsection(meetingSection, "Combatant"),
    architect: extractSubsection(meetingSection, "Architect"),
    moderator: extractSubsection(meetingSection, "Moderator"),
    weightedSynthesis: extractSubsection(meetingSection, "Weighted Synthesis"),
    confidenceByArea: extractSubsection(meetingSection, "Confidence By Area"),
    recommendedRoute: extractSubsection(meetingSection, "Recommended Route").toLowerCase() as VisionMeetingRoute,
  };

  const blockingIssue = getVisionAlignmentBlockingIssue(meeting);
  if (blockingIssue) issues.push(blockingIssue);
  return { issues };
}

export function getMilestonePlanBlockingIssue(content: string): string | null {
  const check = inspectMilestoneRoadmapMarkdown(content);
  return check.issues[0] ?? null;
}
