import {
  WALKTHROUGH_AVERAGE_COMPLETION_LABEL,
  WALKTHROUGH_FORM_CATEGORIES,
} from '@/shared/constants/walkthrough';
import type { WalkthroughSummaryRange } from '@/shared/constants/walkthrough';
import type {
  WalkthroughCheckinDto,
  WalkthroughCommentKey,
  WalkthroughRatingField,
  WalkthroughRatingKey,
} from '@/shared/types/walkthrough';
import type {
  WalkthroughAttentionFlag,
  WalkthroughCategoryAverage,
  WalkthroughCheckInStat,
  WalkthroughHistoryCategory,
  WalkthroughHistoryRow,
  WalkthroughHistoryTone,
  WalkthroughRecognition,
  WalkthroughTeacherFrequency,
  WalkthroughTrendPoint,
} from '@/business/walkthrough/types';

function findCategory(key: WalkthroughRatingKey) {
  return WALKTHROUGH_FORM_CATEGORIES.find((category) => category.key === key);
}

export function getWalkthroughCategoryLabel(key: WalkthroughRatingKey): string {
  return findCategory(key)?.shortLabel ?? key;
}

export function getWalkthroughCategoryMax(key: WalkthroughRatingKey): number {
  return findCategory(key)?.max ?? 4;
}

export function getWalkthroughRating(checkin: WalkthroughCheckinDto, key: WalkthroughRatingKey): number {
  const field: WalkthroughRatingField = `${key}_rating`;
  return checkin[field];
}

export function getWalkthroughComment(checkin: WalkthroughCheckinDto, key: WalkthroughRatingKey): string | null {
  const field: WalkthroughCommentKey = `${key}_comment`;
  return checkin[field];
}

export function getWalkthroughRatingLabel(value: number, key: WalkthroughRatingKey): string {
  if (key === 'emergency_exit') {
    if (value === 3) return 'Visible & Accessible';
    if (value === 2) return 'Needs Adjustment';
    return 'Missing Items';
  }

  if (key === 'lesson_plan') {
    if (value === 3) return 'Posted & Aligned';
    if (value === 2) return 'Not Posted';
    return 'Incomplete';
  }

  if (value === 4) return 'Excellent';
  if (value === 3) return 'Satisfactory';
  if (value === 2) return 'Needs Attention';
  return 'Immediate Support';
}

export function getWalkthroughRatingColor(value: number, maxValue: number): string {
  const pct = value / maxValue;
  if (pct >= 0.85) return 'text-emerald-400';
  if (pct >= 0.6) return 'text-blue-400';
  if (pct >= 0.4) return 'text-amber-400';
  return 'text-red-400';
}

export function getWalkthroughBarColor(value: number, maxValue: number): string {
  const pct = value / maxValue;
  if (pct >= 0.85) return 'bg-emerald-500';
  if (pct >= 0.6) return 'bg-blue-500';
  if (pct >= 0.4) return 'bg-amber-500';
  return 'bg-red-500';
}

export function getWalkthroughStatus(pct: number) {
  if (pct >= 85) {
    return { text: 'text-emerald-400', bg: 'bg-emerald-500/20', border: 'border-emerald-500/30', label: 'Strong' };
  }

  if (pct >= 60) {
    return { text: 'text-blue-400', bg: 'bg-blue-500/20', border: 'border-blue-500/30', label: 'Developing' };
  }

  if (pct >= 40) {
    return { text: 'text-amber-400', bg: 'bg-amber-500/20', border: 'border-amber-500/30', label: 'Developing' };
  }

  return { text: 'text-red-400', bg: 'bg-red-500/20', border: 'border-red-500/30', label: 'Priority Support' };
}

export function getWalkthroughCategoryPct(avg: number, maxValue: number): number {
  return Math.round((avg / maxValue) * 100);
}

export function listWalkthroughTeachers(checkins: readonly WalkthroughCheckinDto[]): readonly string[] {
  return [...new Set(checkins.map((checkin) => checkin.teacher_name))].sort();
}

export function filterWalkthroughCheckins(
  checkins: readonly WalkthroughCheckinDto[],
  selectedTeacher: string,
  timeRange: WalkthroughSummaryRange,
  currentDate: Date = new Date(),
): readonly WalkthroughCheckinDto[] {
  const cutoff = new Date(currentDate);
  cutoff.setDate(cutoff.getDate() - Number(timeRange));

  return checkins.filter((checkin) => {
    const teacherMatches = selectedTeacher === 'all' || checkin.teacher_name === selectedTeacher;
    return teacherMatches && new Date(checkin.check_in_date) >= cutoff;
  });
}

export function calculateWalkthroughOverallPctFromAverages(
  averages: readonly WalkthroughCategoryAverage[],
  checkinCount: number,
): number {
  if (averages.length === 0 || checkinCount === 0) {
    return 0;
  }

  const totalPct = averages.reduce((sum, average) => sum + (average.avg / average.max) * 100, 0);
  return Math.round(totalPct / averages.length);
}

export function createWalkthroughCategoryAverageMap(
  averages: readonly WalkthroughCategoryAverage[],
): ReadonlyMap<WalkthroughRatingKey, WalkthroughCategoryAverage> {
  return new Map(averages.map((average) => [average.key, average]));
}

export function calculateWalkthroughOverallPct(checkin: WalkthroughCheckinDto): number {
  const totalPct = WALKTHROUGH_FORM_CATEGORIES.reduce((sum, category) => {
    const rating = getWalkthroughRating(checkin, category.key);
    return sum + (rating / category.max) * 100;
  }, 0);

  return Math.round(totalPct / WALKTHROUGH_FORM_CATEGORIES.length);
}

export function calculateWalkthroughCurrentMonthCount(
  checkins: readonly WalkthroughCheckinDto[],
  currentDate: Date = new Date(),
): number {
  return checkins.filter((checkin) => {
    const checkinDate = new Date(checkin.check_in_date);
    return checkinDate.getMonth() === currentDate.getMonth()
      && checkinDate.getFullYear() === currentDate.getFullYear();
  }).length;
}

export function buildWalkthroughCheckInStats(
  checkins: readonly WalkthroughCheckinDto[],
  currentDate: Date = new Date(),
): readonly WalkthroughCheckInStat[] {
  return [
    {
      id: 'total',
      label: 'Total Walk-Throughs',
      value: checkins.length.toString(),
      tone: 'indigo',
    },
    {
      id: 'teachers',
      label: 'Teachers Observed',
      value: listWalkthroughTeachers(checkins).length.toString(),
      tone: 'violet',
    },
    {
      id: 'current-month',
      label: 'This Month',
      value: calculateWalkthroughCurrentMonthCount(checkins, currentDate).toString(),
      tone: 'cyan',
    },
    {
      id: 'average-completion',
      label: 'Avg Completion',
      value: WALKTHROUGH_AVERAGE_COMPLETION_LABEL,
      tone: 'emerald',
    },
  ];
}

export function getWalkthroughHistoryTone(overallPct: number): WalkthroughHistoryTone {
  if (overallPct >= 75) {
    return 'strong';
  }

  if (overallPct >= 50) {
    return 'developing';
  }

  return 'priority';
}

export function buildWalkthroughHistoryCategory(
  checkin: WalkthroughCheckinDto,
  key: WalkthroughRatingKey,
): WalkthroughHistoryCategory {
  const value = getWalkthroughRating(checkin, key);
  const max = getWalkthroughCategoryMax(key);

  return {
    key,
    label: getWalkthroughCategoryLabel(key),
    value,
    max,
    tone: getWalkthroughHistoryTone((value / max) * 100),
  };
}

export function buildWalkthroughHistoryRows(
  checkins: readonly WalkthroughCheckinDto[],
): readonly WalkthroughHistoryRow[] {
  return checkins.map((checkin) => {
    const overallPct = calculateWalkthroughOverallPct(checkin);

    return {
      id: checkin.id,
      teacherName: checkin.teacher_name,
      classroom: checkin.classroom,
      date: checkin.check_in_date,
      timeLabel: checkin.check_in_time?.slice(0, 5) || '',
      overallPct,
      tone: getWalkthroughHistoryTone(overallPct),
      categories: WALKTHROUGH_FORM_CATEGORIES.map((category) => buildWalkthroughHistoryCategory(checkin, category.key)),
      notes: checkin.overall_notes,
    };
  });
}

export function calculateWalkthroughCategoryAverages(
  checkins: readonly WalkthroughCheckinDto[],
): readonly WalkthroughCategoryAverage[] {
  return WALKTHROUGH_FORM_CATEGORIES.map((category) => {
    const values = checkins.map((checkin) => getWalkthroughRating(checkin, category.key));

    return {
      key: category.key,
      label: category.shortLabel,
      avg: values.length > 0
        ? values.reduce((sum, value) => sum + value, 0) / values.length
        : 0,
      max: category.max,
      count: values.length,
    };
  });
}

export function calculateWalkthroughTrend(
  checkins: readonly WalkthroughCheckinDto[],
): readonly WalkthroughTrendPoint[] {
  return [...checkins]
    .sort((a, b) => new Date(a.check_in_date).getTime() - new Date(b.check_in_date).getTime())
    .map((checkin) => ({
      date: checkin.check_in_date,
      pct: calculateWalkthroughOverallPct(checkin),
      teacher: checkin.teacher_name,
    }));
}

export function buildWalkthroughAutoSummary(
  checkinCount: number,
  categoryAverages: readonly WalkthroughCategoryAverage[],
  overallPct: number,
  selectedTeacher: string,
  timeRange: WalkthroughSummaryRange,
): string {
  if (checkinCount === 0) {
    return '';
  }

  const strong = categoryAverages
    .filter((average) => (average.avg / average.max) >= 0.75)
    .map((average) => average.label);
  const weak = categoryAverages
    .filter((average) => (average.avg / average.max) < 0.6)
    .map((average) => average.label);
  const teacherLabel = selectedTeacher !== 'all' ? selectedTeacher : 'staff';

  const parts = [`Over the past ${timeRange} days,`];

  if (strong.length > 0) {
    parts.push(`${strong.join(' and ')} show consistent strength.`);
  }

  if (weak.length > 0) {
    parts.push(`${weak.join(' and ')} require${weak.length === 1 ? 's' : ''} moderate attention.`);
  }

  const progressLabel = overallPct >= 75
    ? 'steady progress'
    : overallPct >= 50
      ? 'developing patterns'
      : 'areas needing focused support';

  parts.push(`Overall performance for ${teacherLabel} reflects ${progressLabel}.`);

  return parts.join(' ');
}

export function calculateWalkthroughTeacherFrequencies(
  filteredCheckins: readonly WalkthroughCheckinDto[],
  teachers: readonly string[],
): readonly WalkthroughTeacherFrequency[] {
  const counts = teachers.map((teacher) => ({
    teacher,
    count: filteredCheckins.filter((checkin) => checkin.teacher_name === teacher).length,
  }));
  const maxCount = Math.max(...counts.map((entry) => entry.count), 1);

  return counts.map((entry) => ({
    ...entry,
    pct: (entry.count / maxCount) * 100,
  }));
}

export function findWalkthroughAttentionFlags(
  checkins: readonly WalkthroughCheckinDto[],
  selectedTeacher: string,
): readonly WalkthroughAttentionFlag[] {
  if (selectedTeacher === 'all') {
    return [];
  }

  return WALKTHROUGH_FORM_CATEGORIES.reduce<WalkthroughAttentionFlag[]>((flags, category) => {
    const needsAttention = checkins.filter((checkin) => getWalkthroughRating(checkin, category.key) <= 2);

    if (needsAttention.length >= 2) {
      flags.push({
        teacher: selectedTeacher,
        category: category.shortLabel,
        count: needsAttention.length,
      });
    }

    return flags;
  }, []);
}

export function findWalkthroughRecognitions(
  checkins: readonly WalkthroughCheckinDto[],
  selectedTeacher: string,
): readonly WalkthroughRecognition[] {
  if (selectedTeacher === 'all') {
    return [];
  }

  return WALKTHROUGH_FORM_CATEGORIES.reduce<WalkthroughRecognition[]>((recognitions, category) => {
    const recent = checkins.slice(0, 3);
    if (
      recent.length >= 3
      && recent.every((checkin) => getWalkthroughRating(checkin, category.key) === category.max)
    ) {
      recognitions.push({
        teacher: selectedTeacher,
        category: category.shortLabel,
      });
    }

    return recognitions;
  }, []);
}
