import * as db from './db';

/**
 * Default quarterly theme structure for auto-generating a curriculum.
 * Each quarter has a name and a list of thematic blocks.
 */
const DEFAULT_QUARTERS = [
  {
    quarter: 1,
    name: 'Foundation & Governance',
    themes: [
      'Company Purpose & Values',
      'Governance',
      'People & Culture',
      'Recruitment',
    ],
  },
  {
    quarter: 2,
    name: 'Compliance, Legal & Finance',
    themes: [
      'Privacy',
      'Compliance',
      'Quality',
      'Finance',
    ],
  },
  {
    quarter: 3,
    name: 'Technology & Operations',
    themes: [
      'Strategy',
      'Infrastructure',
      'Workplace',
      'Service Management',
      'Software Delivery',
    ],
  },
  {
    quarter: 4,
    name: 'Business, Marketing & Sustainability',
    themes: [
      'Marketing',
      'Networking',
      'Events',
      'Sustainability',
      'Year Wrap-up',
    ],
  },
];

/**
 * Get the current curriculum year based on a date.
 * Uses the calendar year.
 */
export function getCurriculumYear(date = new Date()) {
  return date.getFullYear();
}

/**
 * Get the quarter number (1-4) for a given ISO week number.
 */
export function getQuarterForWeek(weekNumber) {
  if (weekNumber <= 13) return 1;
  if (weekNumber <= 26) return 2;
  if (weekNumber <= 39) return 3;
  return 4;
}

/**
 * Get the quarter name for a given week number.
 */
export function getQuarterName(weekNumber) {
  const q = getQuarterForWeek(weekNumber);
  return DEFAULT_QUARTERS[q - 1]?.name || `Quarter ${q}`;
}

/**
 * Get the assigned topic for a given week from the curriculum.
 * Returns { topic, curriculumEntry } or { topic: null } if no curriculum exists.
 */
export async function getCurriculumTopic(weekNumber, year) {
  const currYear = year ?? getCurriculumYear();
  const entry = await db.getCurriculumWeek(currYear, weekNumber);

  if (!entry || !entry.topic_id) {
    return { topic: null, curriculumEntry: entry || null };
  }

  // Resolve the topic from the topics collection (ensure it is not excluded)
  const topics = await db.getTopics();
  const topic = topics.find(t => t.id === entry.topic_id && t.learning_relevance !== 'exclude') || null;

  return { topic, curriculumEntry: entry };
}

/**
 * Get the full curriculum for a year, with resolved topic labels.
 */
export async function getFullCurriculum(year) {
  const currYear = year ?? getCurriculumYear();
  const entries = await db.getCurriculum(currYear);
  const topics = await db.getTopics();
  const topicMap = Object.fromEntries(topics.map(t => [t.id, t]));

  return entries.map(entry => ({
    ...entry,
    topic: topicMap[entry.topic_id] || null,
  }));
}

/**
 * Get progress for a user in a given quarter.
 * Returns { completed, total, percentage }.
 */
export async function getQuarterProgress(userId, quarter, year) {
  const currYear = year ?? getCurriculumYear();
  const curriculum = await db.getCurriculum(currYear);
  const quarterWeeks = curriculum.filter(w => w.quarter === quarter);

  let completed = 0;
  for (const week of quarterWeeks) {
    const done = await db.getLearnDone(userId, week.week_number);
    if (done) completed++;
  }

  return {
    completed,
    total: quarterWeeks.length,
    percentage: quarterWeeks.length > 0
      ? Math.round((completed / quarterWeeks.length) * 100)
      : 0,
  };
}

/**
 * Get overall annual progress for a user.
 * Returns { completed, total, percentage }.
 */
export async function getYearProgress(userId, year) {
  const currYear = year ?? getCurriculumYear();
  const curriculum = await db.getCurriculum(currYear);

  if (curriculum.length === 0) {
    return { completed: 0, total: 52, percentage: 0 };
  }

  let completed = 0;
  for (const week of curriculum) {
    const done = await db.getLearnDone(userId, week.week_number);
    if (done) completed++;
  }

  return {
    completed,
    total: curriculum.length,
    percentage: Math.round((completed / curriculum.length) * 100),
  };
}

/**
 * Get upcoming weeks from the curriculum (next N weeks after current).
 */
export async function getUpcomingWeeks(currentWeek, count = 4, year) {
  const currYear = year ?? getCurriculumYear();
  const curriculum = await getFullCurriculum(currYear);

  return curriculum
    .filter(w => w.week_number > currentWeek && w.week_number <= currentWeek + count)
    .sort((a, b) => a.week_number - b.week_number);
}

/**
 * Auto-generate a 52-week curriculum from available topics.
 * Distributes topics evenly across quarters, adds review weeks at 13, 26, 39, 52.
 */
export async function autoGenerateCurriculum(year) {
  const currYear = year ?? getCurriculumYear();
  const topics = await db.getTopics();

  // Filter out 'fact' type topics and 'exclude' relevance topics
  const learningTopics = topics.filter(t => t.type !== 'fact' && t.learning_relevance !== 'exclude');

  const weeks = [];
  const reviewWeeks = [13, 26, 39, 52];

  // Distribute topics across the 48 non-review weeks.
  let topicIndex = 0;

  for (let w = 1; w <= 52; w++) {
    const quarter = getQuarterForWeek(w);

    if (reviewWeeks.includes(w)) {
      // Review / recap week
      weeks.push({
        week_number: w,
        topic_id: '',
        theme: `Q${quarter} Review`,
        quarter,
        is_review_week: true,
        sort_order: w,
      });
    } else if (topicIndex < learningTopics.length) {
      const topic = learningTopics[topicIndex];
      weeks.push({
        week_number: w,
        topic_id: topic.id,
        theme: topic.type || 'General',
        quarter,
        is_review_week: false,
        sort_order: w,
      });
      topicIndex++;
    } else if (learningTopics.length > 0) {
      // If we have more weeks than topics, cycle through topics again
      const topic = learningTopics[topicIndex % learningTopics.length];
      weeks.push({
        week_number: w,
        topic_id: topic.id,
        theme: `${topic.type || 'General'} (Deep Dive)`,
        quarter,
        is_review_week: false,
        sort_order: w,
      });
      topicIndex++;
    } else {
      // No topics at all
      weeks.push({
        week_number: w,
        topic_id: '',
        theme: 'Unassigned',
        quarter,
        is_review_week: false,
        sort_order: w,
      });
    }
  }

  await db.bulkSetCurriculum(currYear, weeks);
  return weeks;
}

/**
 * Check if a curriculum exists for the given year.
 */
export async function hasCurriculum(year) {
  const currYear = year ?? getCurriculumYear();
  const entries = await db.getCurriculum(currYear);
  return entries.length > 0;
}
