import { create } from 'zustand';
import api from './api';

// Phase 1 PR 2 (2026-07-22): store for student cohorts.

export interface Cohort {
  id: number;
  uid: string;
  name: string;
  programme: 'zimsec' | 'igcse' | 'as' | 'a2' | 'primary' | 'other';
  level: string | null;
  academic_year: string | null;
  description: string | null;
  start_date: string | null;
  end_date: string | null;
  is_active: boolean;
  student_count?: number;
  class_count?: number;
  exam_group_count?: number;
  created_at: string;
  updated_at: string;
}

export interface CohortStudent {
  id: number;
  uid: string;
  email: string;
  first_name: string;
  last_name: string;
  status: 'active' | 'inactive' | 'transferred' | 'graduated';
  joined_at: string;
}

export interface CohortClass {
  id: number;
  uid: string;
  name: string;
  section: string | null;
  capacity: number | null;
  class_teacher_id: number | null;
  class_teacher_name?: string | null;
}

export interface CohortExamGroup {
  id: number;
  uid: string;
  name: string;
  exam_type: string | null;
  academic_year: string | null;
  term: string | null;
}

export interface CohortDetail extends Cohort {
  students: CohortStudent[];
  classes: CohortClass[];
  exam_groups: CohortExamGroup[];
}

interface CohortsState {
  cohorts: Cohort[];
  detailById: Record<number, CohortDetail>;
  loading: boolean;
  error: string | null;
  fetchCohorts: (filters?: { programme?: string; academic_year?: string; is_active?: boolean; search?: string }) => Promise<Cohort[]>;
  fetchCohort: (id: number) => Promise<CohortDetail>;
  createCohort: (payload: Partial<Cohort>) => Promise<Cohort>;
  updateCohort: (id: number, payload: Partial<Cohort>) => Promise<Cohort>;
  deleteCohort: (id: number) => Promise<void>;
  addStudents: (cohortId: number, studentIds: number[]) => Promise<{ added: number[]; count: number }>;
  removeStudent: (cohortId: number, studentId: number) => Promise<void>;
  linkClass: (cohortId: number, classId: number) => Promise<void>;
  unlinkClass: (cohortId: number, classId: number) => Promise<void>;
  linkExamGroup: (cohortId: number, examGroupId: number) => Promise<void>;
  unlinkExamGroup: (cohortId: number, examGroupId: number) => Promise<void>;
}

export const useCohortsStore = create<CohortsState>((set, get) => ({
  cohorts: [],
  detailById: {},
  loading: false,
  error: null,

  fetchCohorts: async (filters = {}) => {
    set({ loading: true, error: null });
    try {
      const params = new URLSearchParams();
      if (filters.programme) params.set('programme', filters.programme);
      if (filters.academic_year) params.set('academic_year', filters.academic_year);
      if (filters.is_active !== undefined) params.set('is_active', String(filters.is_active));
      if (filters.search) params.set('search', filters.search);
      const { data } = await api.get(`/cohorts?${params.toString()}`);
      const cohorts = data.cohorts || [];
      set({ cohorts, loading: false });
      return cohorts;
    } catch (err: any) {
      const msg = err.response?.data?.error || err.message || 'Failed to load cohorts';
      set({ loading: false, error: msg });
      throw new Error(msg);
    }
  },

  fetchCohort: async (id) => {
    set({ loading: true, error: null });
    try {
      const { data } = await api.get(`/cohorts/${id}`);
      set((s) => ({ detailById: { ...s.detailById, [id]: data }, loading: false }));
      return data;
    } catch (err: any) {
      const msg = err.response?.data?.error || err.message || 'Failed to load cohort';
      set({ loading: false, error: msg });
      throw new Error(msg);
    }
  },

  createCohort: async (payload) => {
    set({ loading: true, error: null });
    try {
      const { data } = await api.post('/cohorts', payload);
      set((s) => ({ cohorts: [data, ...s.cohorts], loading: false }));
      return data;
    } catch (err: any) {
      const msg = err.response?.data?.error || err.message || 'Failed to create cohort';
      set({ loading: false, error: msg });
      throw new Error(msg);
    }
  },

  updateCohort: async (id, payload) => {
    set({ loading: true, error: null });
    try {
      const { data } = await api.put(`/cohorts/${id}`, payload);
      set((s) => ({
        cohorts: s.cohorts.map((c) => (c.id === id ? data : c)),
        detailById: { ...s.detailById, [id]: { ...(s.detailById[id] || {}), ...data } as CohortDetail },
        loading: false,
      }));
      return data;
    } catch (err: any) {
      const msg = err.response?.data?.error || err.message || 'Failed to update cohort';
      set({ loading: false, error: msg });
      throw new Error(msg);
    }
  },

  deleteCohort: async (id) => {
    set({ loading: true, error: null });
    try {
      await api.delete(`/cohorts/${id}`);
      set((s) => ({ cohorts: s.cohorts.filter((c) => c.id !== id), loading: false }));
    } catch (err: any) {
      const msg = err.response?.data?.error || err.message || 'Failed to delete cohort';
      set({ loading: false, error: msg });
      throw new Error(msg);
    }
  },

  addStudents: async (cohortId, studentIds) => {
    set({ loading: true, error: null });
    try {
      const { data } = await api.post(`/cohorts/${cohortId}/students`, { student_ids: studentIds });
      // Refresh the detail
      await get().fetchCohort(cohortId);
      return data;
    } catch (err: any) {
      const msg = err.response?.data?.error || err.message || 'Failed to add students';
      set({ loading: false, error: msg });
      throw new Error(msg);
    }
  },

  removeStudent: async (cohortId, studentId) => {
    set({ loading: true, error: null });
    try {
      await api.delete(`/cohorts/${cohortId}/students/${studentId}`);
      await get().fetchCohort(cohortId);
    } catch (err: any) {
      const msg = err.response?.data?.error || err.message || 'Failed to remove student';
      set({ loading: false, error: msg });
      throw new Error(msg);
    }
  },

  linkClass: async (cohortId, classId) => {
    set({ loading: true, error: null });
    try {
      await api.post(`/cohorts/${cohortId}/classes`, { class_id: classId });
      await get().fetchCohort(cohortId);
    } catch (err: any) {
      const msg = err.response?.data?.error || err.message || 'Failed to link class';
      set({ loading: false, error: msg });
      throw new Error(msg);
    }
  },

  unlinkClass: async (cohortId, classId) => {
    set({ loading: true, error: null });
    try {
      await api.delete(`/cohorts/${cohortId}/classes/${classId}`);
      await get().fetchCohort(cohortId);
    } catch (err: any) {
      const msg = err.response?.data?.error || err.message || 'Failed to unlink class';
      set({ loading: false, error: msg });
      throw new Error(msg);
    }
  },

  linkExamGroup: async (cohortId, examGroupId) => {
    set({ loading: true, error: null });
    try {
      await api.post(`/cohorts/${cohortId}/exam-groups`, { exam_group_id: examGroupId });
      await get().fetchCohort(cohortId);
    } catch (err: any) {
      const msg = err.response?.data?.error || err.message || 'Failed to link exam group';
      set({ loading: false, error: msg });
      throw new Error(msg);
    }
  },

  unlinkExamGroup: async (cohortId, examGroupId) => {
    set({ loading: true, error: null });
    try {
      await api.delete(`/cohorts/${cohortId}/exam-groups/${examGroupId}`);
      await get().fetchCohort(cohortId);
    } catch (err: any) {
      const msg = err.response?.data?.error || err.message || 'Failed to unlink exam group';
      set({ loading: false, error: msg });
      throw new Error(msg);
    }
  },
}));

export const SUPPORTED_PROGRAMMES = [
  { value: 'zimsec', label: 'ZIMSEC' },
  { value: 'igcse', label: 'IGCSE' },
  { value: 'as', label: 'AS Level' },
  { value: 'a2', label: 'A2 Level' },
  { value: 'primary', label: 'Primary' },
  { value: 'other', label: 'Other' },
] as const;
