/**
 * Teacher Assignments Module - Zustand Store
 *
 * Owns the teacher-side CRUD + lifecycle (draft / published / closed)
 * and grading of student submissions for an assignment. Mirrors the
 * exams.ts reference pattern.
 *
 * Talks to /api/assignments (server/src/controllers/assignments.controller.js):
 *   GET    /                              list (teacher-scoped, ?status=, ?course_id=)
 *   GET    /:id                           single + embedded submissions[]
 *   POST   /                              create (defaults to status='draft')
 *   PUT    /:id                           update editable fields
 *   DELETE /:id                           soft-delete
 *   POST   /:id/publish                   draft -> published (is_published=1)
 *   POST   /:id/unpublish                 published -> draft (is_published=0)
 *   POST   /:id/close                     published -> closed
 *   PUT    /:id/submissions/:sid/grade    grade a single submission
 */

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

export type AssignmentStatus = 'draft' | 'published' | 'closed';

export interface TeacherCourse {
  id: number;
  name: string;
  class_name?: string;
}

export interface Assignment {
  id: number;
  uid?: string;
  course_id: number;
  course_name?: string;
  title: string;
  description?: string;
  instructions?: string;
  due_date?: string | null;
  max_score: number;
  submission_type: 'file' | 'text' | 'online' | 'offline';
  allow_late_submission: number;
  is_published: number;
  status: AssignmentStatus;
  created_at?: string;
  updated_at?: string;
  submission_count?: number;
  graded_count?: number;
  student_count?: number;
}

export interface Submission {
  id: number;
  assignment_id: number;
  student_id: number;
  student_name: string;
  student_email?: string;
  content?: string | null;
  file_path?: string | null;
  submitted_at: string;
  status: 'submitted' | 'graded' | 'returned' | 'late';
  grade?: number | null;
  feedback?: string | null;
  graded_by?: number | null;
  graded_at?: string | null;
}

export interface AssignmentPayload {
  course_id: number;
  title: string;
  description?: string;
  instructions?: string;
  due_date?: string | null;
  max_score?: number;
  submission_type?: Assignment['submission_type'];
  allow_late_submission?: boolean;
}

interface TeacherAssignmentStore {
  assignments: Assignment[];
  current: Assignment | null;
  submissions: Submission[];
  isLoading: boolean;
  isMutating: boolean;
  error: string | null;

  fetchAssignments: (filters?: { status?: AssignmentStatus; course_id?: number }) => Promise<void>;
  fetchAssignment: (id: number) => Promise<void>;
  createAssignment: (payload: AssignmentPayload) => Promise<Assignment>;
  updateAssignment: (id: number, payload: Partial<AssignmentPayload> & { status?: AssignmentStatus }) => Promise<Assignment>;
  deleteAssignment: (id: number) => Promise<void>;
  publishAssignment: (id: number) => Promise<Assignment>;
  unpublishAssignment: (id: number) => Promise<Assignment>;
  gradeSubmission: (assignmentId: number, submissionId: number, payload: { grade: number; feedback?: string }) => Promise<Submission>;
  returnSubmission: (assignmentId: number, submissionId: number) => Promise<Submission>;

  reset: () => void;
}

export const useTeacherAssignmentStore = create<TeacherAssignmentStore>((set) => ({
  assignments: [],
  current: null,
  submissions: [],
  isLoading: false,
  isMutating: false,
  error: null,

  fetchAssignments: async (filters) => {
    set({ isLoading: true, error: null });
    try {
      const params: Record<string, string | number> = {};
      if (filters?.status) params.status = filters.status;
      if (filters?.course_id) params.course_id = filters.course_id;
      const res = await api.get('/assignments', { params });
      set({ assignments: res.data, isLoading: false });
    } catch (error: any) {
      set({ error: error.response?.data?.error || error.message, isLoading: false });
      throw error;
    }
  },

  fetchAssignment: async (id) => {
    set({ isLoading: true, error: null });
    try {
      const res = await api.get(`/assignments/${id}`);
      const { submissions, ...assignment } = res.data;
      set({
        current: assignment,
        submissions: submissions || [],
        isLoading: false,
      });
    } catch (error: any) {
      set({ error: error.response?.data?.error || error.message, isLoading: false });
      throw error;
    }
  },

  createAssignment: async (payload) => {
    set({ isMutating: true, error: null });
    try {
      const res = await api.post('/assignments', payload);
      set((state) => ({ assignments: [res.data, ...state.assignments], isMutating: false }));
      return res.data;
    } catch (error: any) {
      set({ error: error.response?.data?.error || error.message, isMutating: false });
      throw error;
    }
  },

  updateAssignment: async (id, payload) => {
    set({ isMutating: true, error: null });
    try {
      const res = await api.put(`/assignments/${id}`, payload);
      const updated: Assignment = res.data;
      set((state) => ({
        assignments: state.assignments.map((a) => (a.id === id ? { ...a, ...updated } : a)),
        current: state.current?.id === id ? { ...state.current, ...updated } : state.current,
        isMutating: false,
      }));
      return updated;
    } catch (error: any) {
      set({ error: error.response?.data?.error || error.message, isMutating: false });
      throw error;
    }
  },

  deleteAssignment: async (id) => {
    set({ isMutating: true, error: null });
    try {
      await api.delete(`/assignments/${id}`);
      set((state) => ({
        assignments: state.assignments.filter((a) => a.id !== id),
        current: state.current?.id === id ? null : state.current,
        isMutating: false,
      }));
    } catch (error: any) {
      set({ error: error.response?.data?.error || error.message, isMutating: false });
      throw error;
    }
  },

  publishAssignment: async (id) => {
    set({ isMutating: true, error: null });
    try {
      const res = await api.post(`/assignments/${id}/publish`);
      const updated: Assignment = res.data;
      set((state) => ({
        assignments: state.assignments.map((a) => (a.id === id ? { ...a, ...updated } : a)),
        current: state.current?.id === id ? { ...state.current, ...updated } : state.current,
        isMutating: false,
      }));
      return updated;
    } catch (error: any) {
      set({ error: error.response?.data?.error || error.message, isMutating: false });
      throw error;
    }
  },

  unpublishAssignment: async (id) => {
    set({ isMutating: true, error: null });
    try {
      const res = await api.post(`/assignments/${id}/unpublish`);
      const updated: Assignment = res.data;
      set((state) => ({
        assignments: state.assignments.map((a) => (a.id === id ? { ...a, ...updated } : a)),
        current: state.current?.id === id ? { ...state.current, ...updated } : state.current,
        isMutating: false,
      }));
      return updated;
    } catch (error: any) {
      set({ error: error.response?.data?.error || error.message, isMutating: false });
      throw error;
    }
  },

  closeAssignment: async (id) => {
    set({ isMutating: true, error: null });
    try {
      const res = await api.post(`/assignments/${id}/close`);
      const updated: Assignment = res.data;
      set((state) => ({
        assignments: state.assignments.map((a) => (a.id === id ? { ...a, ...updated } : a)),
        current: state.current?.id === id ? { ...state.current, ...updated } : state.current,
        isMutating: false,
      }));
      return updated;
    } catch (error: any) {
      set({ error: error.response?.data?.error || error.message, isMutating: false });
      throw error;
    }
  },

  gradeSubmission: async (assignmentId, submissionId, payload) => {
    set({ isMutating: true, error: null });
    try {
      const res = await api.put(`/assignments/${assignmentId}/submissions/${submissionId}/grade`, payload);
      const graded: Submission = res.data;
      set((state) => ({
        submissions: state.submissions.map((s) => (s.id === submissionId ? { ...s, ...graded } : s)),
        isMutating: false,
      }));
      return graded;
    } catch (error: any) {
      set({ error: error.response?.data?.error || error.message, isMutating: false });
      throw error;
    }
  },

  returnSubmission: async (assignmentId, submissionId) => {
    set({ isMutating: true, error: null });
    try {
      const res = await api.post(`/assignments/${assignmentId}/submissions/${submissionId}/return`);
      const returned: Submission = res.data;
      set((state) => ({
        submissions: state.submissions.map((s) => (s.id === submissionId ? { ...s, ...returned } : s)),
        isMutating: false,
      }));
      return returned;
    } catch (error: any) {
      set({ error: error.response?.data?.error || error.message, isMutating: false });
      throw error;
    }
  },

  reset: () => set({ current: null, submissions: [], error: null }),
}));

export default useTeacherAssignmentStore;