/**
 * Derived data-shape logic for the school detail pages.
 *
 * Pure functions with no React dependency, so the server route can decide
 * which sections exist without pulling in a client component. Extracted from
 * SchoolDetailView, which owned this logic inline while it was a client
 * component.
 */

import type {
  School, SchoolResult, AbsenceData, SchoolCensus,
  OfstedInspection, SchoolAdmissions, SchoolDeprivation, SchoolFinance,
} from './types';
import { isSpecialSchool } from './utils';

export interface SchoolFlagsInput {
  schoolInfo: School;
  yearlyData: SchoolResult[];
  absenceData: AbsenceData | null;
  census: SchoolCensus | null;
  deprivation: SchoolDeprivation | null;
  finance: SchoolFinance | null;
}

export interface SchoolFlags {
  latestResults: SchoolResult | null;
  isAllThrough: boolean;
  isSecondary: boolean;
  isPrimary: boolean;
  hasGenderSplit: boolean;
  hasInclusionData: boolean;
  hasSchoolLife: boolean;
  hasDeprivation: boolean;
  hasFinance: boolean;
  hasLocation: boolean;
  hasKS2Results: boolean;
  hasKS4Results: boolean;
  hasAnyResults: boolean;
  isSpecial: boolean;
  ks2Placeholder: boolean;
  suppressKs2Comparison: boolean;
  suppressKs4Comparison: boolean;
}

export interface NavItem {
  id: string;
  label: string;
}

export function computeSchoolFlags({
  schoolInfo, yearlyData, absenceData, census, deprivation, finance,
}: SchoolFlagsInput): SchoolFlags {
  const latestResults = yearlyData.length > 0 ? yearlyData[yearlyData.length - 1] : null;

  // Phase detection. All-through schools cover BOTH key stages, so they are
  // neither "pure primary" nor "pure secondary": isSecondary stays true (they
  // have KS4 data) but isAllThrough gates the primary-only content (KS2 SATs,
  // KS2 trend) back on and switches phase-specific copy to an all-ages framing.
  const phase = schoolInfo.phase ?? '';
  const isAllThrough = phase.toLowerCase() === 'all-through';
  const isSecondary = phase.toLowerCase().includes('secondary') || isAllThrough;
  const isPrimary = !isSecondary;

  // Gender split availability (only meaningful for Mixed schools with census data)
  const isMixedSchool = schoolInfo.gender === 'Mixed' || schoolInfo.gender == null;
  const hasGenderSplit = !!(isMixedSchool
    && census?.female_pupils != null
    && census?.male_pupils != null
    && (census.female_pupils + census.male_pupils) > 0);

  // Guard for Pupils & Inclusion — only show if at least one metric is available
  const hasInclusionData = (latestResults?.disadvantaged_pct != null)
    || (latestResults?.eal_pct != null)
    || (latestResults?.sen_support_pct != null)
    || hasGenderSplit;

  const hasSchoolLife = absenceData != null;
  const hasDeprivation = deprivation != null && deprivation.idaci_decile != null;
  const hasFinance = finance != null && finance.per_pupil_spend != null;
  const hasLocation = schoolInfo.latitude != null && schoolInfo.longitude != null;

  // Determine whether this school has KS2 or KS4 results to show
  const hasKS2Results = latestResults != null && latestResults.rwm_expected_pct != null;
  const hasKS4Results = latestResults != null && latestResults.attainment_8_score != null;
  const hasAnyResults = hasKS2Results || hasKS4Results;

  // Special schools / PRUs / AP: their pupils sit the same tests but very few
  // reach the mainstream "expected standard", so a 0% headline and an England
  // comparison portray them as failing against a benchmark that doesn't fit.
  const isSpecial = isSpecialSchool(schoolInfo);
  // Belt-and-braces for KS2: a whole-row zero attainment (every subject 0 — a
  // special/suppressed signature) is a placeholder, not a real result. This
  // needs ALL of RWM + reading + writing + maths to be 0, so a genuine 0%
  // combined (some pupils met individual subjects but not all three) stays
  // comparable. Attainment 8 is a single 0–80 score with no subject breakdown
  // to form such a signature, so KS4 keys off establishment type only — a
  // genuine (if extreme) 0.0 still shows its real figure and comparison.
  const ks2Placeholder = latestResults != null
    && latestResults.rwm_expected_pct === 0
    && (latestResults.reading_expected_pct ?? 0) === 0
    && (latestResults.writing_expected_pct ?? 0) === 0
    && (latestResults.maths_expected_pct ?? 0) === 0;
  // Whether to drop the England-average deltas / national markers / "below"
  // framing on the attainment measures.
  const suppressKs2Comparison = isSpecial || ks2Placeholder;
  const suppressKs4Comparison = isSpecial;

  return {
    latestResults,
    isAllThrough, isSecondary, isPrimary,
    hasGenderSplit, hasInclusionData, hasSchoolLife,
    hasDeprivation, hasFinance, hasLocation,
    hasKS2Results, hasKS4Results, hasAnyResults,
    isSpecial, ks2Placeholder,
    suppressKs2Comparison, suppressKs4Comparison,
  };
}

export interface NavItemsInput {
  ofsted: OfstedInspection | null;
  admissions: SchoolAdmissions | null;
  yearlyDataLength: number;
}

/**
 * Build section nav items dynamically — only sections with data.
 * Order is engagement-led (from section_nav_used analytics): the most-sought
 * sections — results, admissions, inclusion, history — sit near the top,
 * after the recognised Ofsted badge; low-demand context sections stay last.
 *
 * These conditions MUST match the conditions the section composers use to
 * render, or the nav will link to sections that do not exist.
 */
export function buildNavItems(
  flags: SchoolFlags,
  { ofsted, admissions, yearlyDataLength }: NavItemsInput,
): NavItem[] {
  const navItems: NavItem[] = [];
  if (ofsted) navItems.push({ id: 'ofsted', label: 'Ofsted' });
  if (flags.hasAnyResults) {
    navItems.push({
      id: 'results',
      label: flags.isAllThrough ? 'Results' : flags.isSecondary ? 'GCSEs' : 'SATs',
    });
  }
  if (admissions) navItems.push({ id: 'admissions', label: 'Admissions' });
  if (flags.hasInclusionData) navItems.push({ id: 'inclusion', label: 'Pupils' });
  if (yearlyDataLength > 0) navItems.push({ id: 'history', label: 'History' });
  if (flags.hasSchoolLife) navItems.push({ id: 'school-life', label: 'School Life' });
  if (flags.hasDeprivation) navItems.push({ id: 'local-area', label: 'Local Area' });
  if (flags.hasFinance) navItems.push({ id: 'finances', label: 'Finances' });
  return navItems;
}

// ---------------------------------------------------------------------------
// Secondary pages
//
// The secondary view is not a variant of the primary one: it has its own
// section ids ('gcse', 'wellbeing'), its own flags, and gates History on
// MORE THAN ONE year rather than at least one. Kept as separate functions so
// neither phase's behaviour bends to accommodate the other.
// ---------------------------------------------------------------------------

export interface SecondaryFlags {
  latestResults: SchoolResult | null;
  hasSixthForm: boolean;
  hasFinance: boolean;
  hasDeprivation: boolean;
  hasLocation: boolean;
  hasWellbeing: boolean;
  hasResults: boolean;
  /** Progress 8 was suspended from the 2024/25 cohort onwards. */
  p8Suspended: boolean;
  isSpecial: boolean;
  suppressComparison: boolean;
}

export function computeSecondaryFlags({
  schoolInfo, yearlyData, deprivation, finance,
}: Omit<SchoolFlagsInput, 'absenceData' | 'census'>): SecondaryFlags {
  const latestResults = yearlyData.length > 0 ? yearlyData[yearlyData.length - 1] : null;

  // GIAS OfficialSixthForm flag; missing (pipeline not yet re-run) => false.
  const hasSixthForm = schoolInfo.has_sixth_form ?? false;
  const hasFinance = finance != null && finance.per_pupil_spend != null;
  const hasDeprivation = deprivation != null && deprivation.idaci_decile != null;
  const hasLocation = schoolInfo.latitude != null && schoolInfo.longitude != null;
  const hasWellbeing = (latestResults?.sen_support_pct != null || latestResults?.sen_ehcp_pct != null) || hasDeprivation;
  const p8Suspended = latestResults != null && latestResults.year >= 202425;
  const hasResults = latestResults?.attainment_8_score != null;

  // Special schools / PRUs / AP sit the same GCSEs but teach pupils with SEND,
  // so their headline attainment is far below the mainstream average by design.
  // Drop the England comparison + "below" framing so the page doesn't portray
  // them as failing against a benchmark that doesn't fit. Attainment 8 is a
  // single 0–80 score with no subject breakdown to test for a placeholder, so
  // this keys off establishment type only — a genuine (if extreme) 0.0 at a
  // mainstream school still shows its real value and comparison.
  const isSpecial = isSpecialSchool(schoolInfo);
  const suppressComparison = isSpecial;

  return {
    latestResults, hasSixthForm, hasFinance, hasDeprivation, hasLocation,
    hasWellbeing, hasResults: !!hasResults, p8Suspended, isSpecial, suppressComparison,
  };
}

/**
 * Build nav items for a secondary page.
 * Engagement-led order (matches the primary page): recognised Ofsted badge,
 * then the most-sought sections — results, admissions, history — with the
 * experience and context sections following.
 */
export function buildSecondaryNavItems(
  flags: SecondaryFlags,
  { ofsted, admissions, yearlyDataLength }: NavItemsInput,
): NavItem[] {
  const navItems: NavItem[] = [];
  if (ofsted) navItems.push({ id: 'ofsted', label: 'Ofsted' });
  if (flags.hasResults) navItems.push({ id: 'gcse', label: 'GCSEs' });
  if (admissions) navItems.push({ id: 'admissions', label: 'Admissions' });
  if (yearlyDataLength > 1) navItems.push({ id: 'history', label: 'History' });
  if (flags.hasWellbeing) navItems.push({ id: 'wellbeing', label: 'Wellbeing' });
  if (flags.hasFinance) navItems.push({ id: 'finances', label: 'Finances' });
  return navItems;
}
