/**
 * Tests Module - Zustand Store
 */

import { create } from 'zustand';
import api from './api';
import type { Attachment } from './attachments';

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

export interface TestPaper {
  id: number;
  uid?: string;
  subject_id: number;
  class_id?: number | null;
  title: string;
  description?: string;
  instructions?: string;
  test_date?: string | null;
  duration_minutes?: number | null;
  max_score?: number;
  allow_late_submission?: boolean;
  is_published?: boolean;
  status: TestStatus | string;
  created_by?: number | null;
  created_at?: string;
  updated_at?: string;
  attachments?: Attachment[];
  subject_name?: string;
  class_name?: string;
  submission_count?: number;
  graded_count?: number;
}

export interface TestSubmission {
  id: number;
  uid?: string;
  test_id: number;
  student_id: number;
  content?: string;
  submitted_at?: string;
  status: 'submitted' | 'graded' | 'returned' | 'late' | string;
  grade?: number | null;
  feedback?: string | null;
  graded_by?: number | null;
  graded_at?: string | null;
  attachments?: Attachment[];
  marked_scripts?: Attachment[];
  student_name?: string;
  student_email?: string;
}

interface TestState {
  items: TestPaper[];
  current: TestPaper | null;
  submissions: Record<number, TestSubmission[]>;
  loading: boolean;
  error: string | null;

  list: () => Promise<TestPaper[]>;
  get: (id: number) => Promise<TestPaper | null>;
  create: (data: Partial<TestPaper>) => Promise<TestPaper>;
  update: (id: number, data: Partial<TestPaper>) => Promise<TestPaper>;
  remove: (id: number) => Promise<void>;
  submit: (testId: number, payload: { content?: string; file?: File }) => Promise<TestSubmission>;
  grade: (testId: number, submissionId: number, payload: { grade: number; feedback?: string }) => Promise<TestSubmission>;
  returnSubmission: (testId: number, submissionId: number) => Promise<TestSubmission>;
  mySubmissions: () => Promise<TestSubmission[]>;
}

export const useTestStore = create<TestState>((set, get) => ({
  items: [],
  current: null,
  submissions: {},
  loading: false,
  error: null,

  list: async () => {
    set({ loading: true, error: null });
    try {
      const res = await api.get('/tests');
      const rows: TestPaper[] = Array.isArray(res.data) ? res.data : [];
      set({ items: rows, loading: false });
      return rows;
    } catch (err: any) {
      set({ items: [], loading: false, error: err?.response?.data?.error || err.message });
      return [];
    }
  },

  get: async (id) => {
    set({ loading: true, error: null });
    try {
      const res = await api.get(`/tests/${id}`);
      const data: TestPaper = res.data;
      set(state => ({
        current: data,
        submissions: {
          ...state.submissions,
          [id]: (data as any).submissions || []
        },
        loading: false
      }));
      return data;
    } catch (err: any) {
      set({ loading: false, error: err?.response?.data?.error || err.message });
      return null;
    }
  },

  create: async (data) => {
    set({ loading: true, error: null });
    try {
      const res = await api.post('/tests', data);
      const created: TestPaper = res.data;
      set(state => ({
        items: [created, ...state.items],
        loading: false
      }));
      return created;
    } catch (err: any) {
      set({ loading: false, error: err?.response?.data?.error || err.message });
      throw err;
    }
  },

  update: async (id, data) => {
    set({ loading: true, error: null });
    try {
      const res = await api.put(`/tests/${id}`, data);
      const updated: TestPaper = res.data;
      set(state => ({
        items: state.items.map(item => item.id === id ? updated : item),
        current: state.current?.id === id ? updated : state.current,
        loading: false
      }));
      return updated;
    } catch (err: any) {
      set({ loading: false, error: err?.response?.data?.error || err.message });
      throw err;
    }
  },

  remove: async (id) => {
    set({ loading: true, error: null });
    try {
      await api.delete(`/tests/${id}`);
      set(state => ({
        items: state.items.filter(item => item.id !== id),
        current: state.current?.id === id ? null : state.current,
        loading: false
      }));
    } catch (err: any) {
      set({ loading: false, error: err?.response?.data?.error || err.message });
      throw err;
    }
  },

  submit: async (testId, payload) => {
    set({ loading: true, error: null });
    try {
      const formData = new FormData();
      if (payload.content) formData.append('content', payload.content);
      if (payload.file) formData.append('file', payload.file);

      const res = await api.post(`/tests/${testId}/submit`, formData, {
        headers: { 'Content-Type': 'multipart/form-data' }
      });
      const submission: TestSubmission = res.data;

      // Update submissions in local state
      set(state => {
        const list = state.submissions[testId] || [];
        const nextList = list.filter(s => s.student_id !== submission.student_id).concat([submission]);
        return {
          submissions: { ...state.submissions, [testId]: nextList },
          loading: false
        };
      });

      return submission;
    } catch (err: any) {
      set({ loading: false, error: err?.response?.data?.error || err.message });
      throw err;
    }
  },

  grade: async (testId, submissionId, payload) => {
    set({ loading: true, error: null });
    try {
      const res = await api.put(`/tests/${testId}/submissions/${submissionId}/grade`, payload);
      const updatedSub: TestSubmission = res.data;

      set(state => {
        const list = state.submissions[testId] || [];
        const nextList = list.map(s => s.id === submissionId ? { ...s, ...updatedSub } : s);
        return {
          submissions: { ...state.submissions, [testId]: nextList },
          loading: false
        };
      });

      return updatedSub;
    } catch (err: any) {
      set({ loading: false, error: err?.response?.data?.error || err.message });
      throw err;
    }
  },

  returnSubmission: async (testId, submissionId) => {
    set({ loading: true, error: null });
    try {
      const res = await api.post(`/tests/${testId}/submissions/${submissionId}/return`);
      const updatedSub: TestSubmission = res.data;

      set(state => {
        const list = state.submissions[testId] || [];
        const nextList = list.map(s => s.id === submissionId ? { ...s, ...updatedSub } : s);
        return {
          submissions: { ...state.submissions, [testId]: nextList },
          loading: false
        };
      });

      return updatedSub;
    } catch (err: any) {
      set({ loading: false, error: err?.response?.data?.error || err.message });
      throw err;
    }
  },

  mySubmissions: async () => {
    set({ loading: true, error: null });
    try {
      const res = await api.get('/tests/my/submissions');
      set({ loading: false });
      return res.data;
    } catch (err: any) {
      set({ loading: false, error: err?.response?.data?.error || err.message });
      return [];
    }
  }
}));

export default useTestStore;
