import type { FastifyInstance } from 'fastify';
import { z } from 'zod';
import { getPocketBase } from '../lib/pocketbase.js';
import type { EmployeeState } from '../types.js';

const AdvanceBodySchema = z.object({
  completedWeek: z.number().min(1).max(26),
});

export async function employeeRoutes(app: FastifyInstance): Promise<void> {
  // GET /state/:userId
  app.get<{ Params: { userId: string } }>('/state/:userId', async (request, reply) => {
    const pb = await getPocketBase();

    const records = await pb.collection('employee_curriculum_state').getFullList({
      filter: `user = "${request.params.userId}"`,
      expand: 'active_version',
    });

    if (records.length === 0) {
      return reply.status(404).send({ error: 'Employee curriculum state not found' });
    }

    const state = records[0]!;
    const currentWeek = state['current_week'] as number;
    const activeVersionId = state['active_version'] as string;

    // Fetch the week record for next session
    const nextWeekRecords = await pb.collection('curriculum_weeks').getFullList({
      filter: `curriculum_version = "${activeVersionId}" && week_number = ${currentWeek}`,
      expand: 'theme,topics',
    });

    let nextSessionTheme: EmployeeState['nextSessionTheme'] = null;
    let nextSessionTopics: EmployeeState['nextSessionTopics'] = [];

    const nextWeek = nextWeekRecords[0];
    if (nextWeek) {
      const expand = (nextWeek['expand'] as Record<string, unknown>) ?? {};
      const theme = expand['theme'] as Record<string, unknown> | undefined;
      if (theme) {
        nextSessionTheme = { id: theme['id'] as string, title: theme['title'] as string };
      }
      const rawTopics = expand['topics'];
      if (Array.isArray(rawTopics)) {
        nextSessionTopics = rawTopics.map((t: unknown) => {
          const tr = t as Record<string, unknown>;
          return {
            id: tr['id'] as string,
            title: tr['title'] as string,
            complexityWeight: (tr['complexity_weight'] as number) ?? 1,
          };
        });
      }
    }

    const employeeState: EmployeeState = {
      userId: request.params.userId,
      currentCycle: state['current_cycle'] as number,
      currentWeek,
      startDate: state['start_date'] as string,
      activeVersionId,
      nextSessionTheme,
      nextSessionTopics,
    };

    return reply.send(employeeState);
  });

  // POST /advance/:userId
  app.post<{ Params: { userId: string } }>('/advance/:userId', async (request, reply) => {
    const body = AdvanceBodySchema.safeParse(request.body);
    if (!body.success) {
      return reply.status(400).send({ error: 'Invalid request body', details: body.error.issues });
    }

    const pb = await getPocketBase();

    const records = await pb.collection('employee_curriculum_state').getFullList({
      filter: `user = "${request.params.userId}"`,
    });

    if (records.length === 0) {
      return reply.status(404).send({ error: 'Employee curriculum state not found' });
    }

    const state = records[0]!;
    const currentWeek = state['current_week'] as number;
    const currentCycle = state['current_cycle'] as number;

    if (body.data.completedWeek !== currentWeek) {
      return reply.status(409).send({
        error: 'completedWeek does not match employee current_week',
        expected: currentWeek,
        received: body.data.completedWeek,
      });
    }

    let newWeek: number;
    let newCycle: number;
    let newActiveVersion: string;

    if (currentWeek === 26) {
      // Cycle transition
      newWeek = 1;
      newCycle = currentCycle + 1;

      // Use current active curriculum version for new cycle
      const activeVersions = await pb.collection('curriculum_versions').getFullList({
        filter: 'status = "active"',
        perPage: 1,
      });
      newActiveVersion = activeVersions[0]?.id ?? (state['active_version'] as string);
    } else {
      newWeek = currentWeek + 1;
      newCycle = currentCycle;
      newActiveVersion = state['active_version'] as string;
    }

    const updates: Record<string, unknown> = {
      current_week: newWeek,
      current_cycle: newCycle,
      active_version: newActiveVersion,
    };

    if (currentWeek === 26) {
      updates['start_date'] = new Date().toISOString();
    }

    await pb.collection('employee_curriculum_state').update(state.id, updates);

    return reply.send({
      userId: request.params.userId,
      previousWeek: currentWeek,
      currentWeek: newWeek,
      currentCycle: newCycle,
      cycleTransition: currentWeek === 26,
    });
  });
}
