import { 
  User, 
  Student, 
  Course, 
  Grade, 
  Attendance, 
  Assignment, 
  Announcement, 
  Message, 
  Document, 
  PaymentMethod, 
  Fee,
  BankAccount
} from '@/types';

// Mock data imports
import { users } from '@/mocks/users';
import { students } from '@/mocks/students';
import { courses } from '@/mocks/courses';
import { grades } from '@/mocks/grades';
import { attendance } from '@/mocks/attendance';
import { assignments } from '@/mocks/assignments';
import { announcements } from '@/mocks/announcements';
import { messages } from '@/mocks/messages';
import { schedule } from '@/mocks/schedule';
import { events } from '@/mocks/events';
import { fees } from '@/mocks/fees';

// Helper function to simulate API delay
const delay = (ms: number) => new Promise(resolve => setTimeout(resolve, ms));

// Authentication Service
export const authService = {
  login: async (email: string, password: string): Promise<User> => {
    await delay(1000);
    
    const user = users.find(u => u.email === email);
    
    if (!user) {
      throw new Error('User not found');
    }
    
    // In a real app, you would verify the password here
    return user;
  },
  
  logout: async (): Promise<void> => {
    await delay(500);
    // In a real app, you would clear tokens, etc.
  },
  
  register: async (userData: Partial<User>): Promise<User> => {
    await delay(1500);
    
    // Check if user already exists
    if (users.some(u => u.email === userData.email)) {
      throw new Error('User already exists');
    }
    
    // Create new user
    const newUser: User = {
      id: `user_${Date.now()}`,
      name: userData.name || '',
      email: userData.email || '',
      role: userData.role || 'student',
      ...userData,
    };
    
    // In a real app, you would save the user to the database
    
    return newUser;
  },
  
  resetPassword: async (email: string): Promise<void> => {
    await delay(1000);
    
    const user = users.find(u => u.email === email);
    
    if (!user) {
      throw new Error('User not found');
    }
    
    // In a real app, you would send a password reset email
  },
};

// Student Service
export const studentService = {
  getStudent: async (studentId: string): Promise<Student> => {
    await delay(800);
    
    const student = students.find(s => s.id === studentId);
    
    if (!student) {
      throw new Error('Student not found');
    }
    
    return student;
  },
  
  getStudentsByParent: async (parentId: string): Promise<Student[]> => {
    await delay(800);
    
    const studentList = students.filter(s => s.parentId === parentId);
    
    return studentList;
  },
  
  getStudentsByTeacher: async (teacherId: string): Promise<Student[]> => {
    await delay(800);
    
    const studentList = students.filter(s => s.teacherId === teacherId);
    
    return studentList;
  },
  
  updateStudent: async (studentId: string, data: Partial<Student>): Promise<Student> => {
    await delay(1000);
    
    const student = students.find(s => s.id === studentId);
    
    if (!student) {
      throw new Error('Student not found');
    }
    
    // Update student data
    const updatedStudent = { ...student, ...data };
    
    // In a real app, you would save the updated student to the database
    
    return updatedStudent;
  },
};

// Course Service
export const courseService = {
  getCourses: async (grade?: string): Promise<Course[]> => {
    await delay(800);
    
    if (grade) {
      return courses.filter(c => c.grade === grade);
    }
    
    return courses;
  },
  
  getCoursesByTeacher: async (teacherId: string): Promise<Course[]> => {
    await delay(800);
    
    return courses.filter(c => c.teacherId === teacherId);
  },
  
  getCourse: async (courseId: string): Promise<Course> => {
    await delay(800);
    
    const course = courses.find(c => c.id === courseId);
    
    if (!course) {
      throw new Error('Course not found');
    }
    
    return course;
  },
};

// Grade Service
export const gradeService = {
  getGradesByStudent: async (studentId: string): Promise<Grade[]> => {
    await delay(800);
    
    return grades.filter(g => g.studentId === studentId);
  },
  
  getGradesByCourse: async (courseId: string): Promise<Grade[]> => {
    await delay(800);
    
    return grades.filter(g => g.courseId === courseId);
  },
  
  addGrade: async (grade: Partial<Grade>): Promise<Grade> => {
    await delay(1000);
    
    const newGrade: Grade = {
      id: `grade_${Date.now()}`,
      studentId: grade.studentId || '',
      courseId: grade.courseId || '',
      courseName: grade.courseName || '',
      grade: grade.grade || '',
      score: grade.score || 0,
      term: grade.term || '',
      year: grade.year || '',
      feedback: grade.feedback,
    };
    
    // In a real app, you would save the grade to the database
    
    return newGrade;
  },
  
  updateGrade: async (gradeId: string, data: Partial<Grade>): Promise<Grade> => {
    await delay(1000);
    
    const grade = grades.find(g => g.id === gradeId);
    
    if (!grade) {
      throw new Error('Grade not found');
    }
    
    // Update grade data
    const updatedGrade = { ...grade, ...data };
    
    // In a real app, you would save the updated grade to the database
    
    return updatedGrade;
  },
};

// Attendance Service
export const attendanceService = {
  getAttendanceByStudent: async (studentId: string): Promise<Attendance[]> => {
    await delay(800);
    
    return attendance.filter(a => a.studentId === studentId);
  },
  
  addAttendance: async (attendanceData: Partial<Attendance>): Promise<Attendance> => {
    await delay(1000);
    
    const newAttendance: Attendance = {
      id: `attendance_${Date.now()}`,
      studentId: attendanceData.studentId || '',
      date: attendanceData.date || new Date().toISOString(),
      status: attendanceData.status || 'present',
      reason: attendanceData.reason,
    };
    
    // In a real app, you would save the attendance to the database
    
    return newAttendance;
  },
  
  updateAttendance: async (attendanceId: string, data: Partial<Attendance>): Promise<Attendance> => {
    await delay(1000);
    
    const attendanceItem = attendance.find(a => a.id === attendanceId);
    
    if (!attendanceItem) {
      throw new Error('Attendance record not found');
    }
    
    // Update attendance data
    const updatedAttendance = { ...attendanceItem, ...data };
    
    // In a real app, you would save the updated attendance to the database
    
    return updatedAttendance;
  },
};

// Assignment Service
export const assignmentService = {
  getAssignmentsByStudent: async (studentId: string): Promise<Assignment[]> => {
    await delay(800);
    
    return assignments;
  },
  
  getAssignmentsByCourse: async (courseId: string): Promise<Assignment[]> => {
    await delay(800);
    
    return assignments.filter(a => a.courseId === courseId);
  },
  
  submitAssignment: async (assignmentId: string, submission: any): Promise<Assignment> => {
    await delay(1000);
    
    const assignment = assignments.find(a => a.id === assignmentId);
    
    if (!assignment) {
      throw new Error('Assignment not found');
    }
    
    // Update assignment status
    const updatedAssignment: Assignment = { 
      ...assignment, 
      status: 'submitted' as const,
      // In a real app, you would store the submission data
    };
    
    // In a real app, you would save the updated assignment to the database
    
    return updatedAssignment;
  },
  
  gradeAssignment: async (assignmentId: string, score: number, feedback?: string): Promise<Assignment> => {
    await delay(1000);
    
    const assignment = assignments.find(a => a.id === assignmentId);
    
    if (!assignment) {
      throw new Error('Assignment not found');
    }
    
    // Update assignment with grade
    const updatedAssignment: Assignment = { 
      ...assignment, 
      status: 'graded' as const,
      score,
      feedback,
    };
    
    // In a real app, you would save the updated assignment to the database
    
    return updatedAssignment;
  },
};

// Announcement Service
export const announcementService = {
  getAnnouncements: async (): Promise<Announcement[]> => {
    await delay(800);
    
    return announcements;
  },
  
  createAnnouncement: async (announcement: Partial<Announcement>): Promise<Announcement> => {
    await delay(1000);
    
    const newAnnouncement: Announcement = {
      id: `announcement_${Date.now()}`,
      title: announcement.title || '',
      content: announcement.content || '',
      date: announcement.date || new Date().toISOString(),
      author: announcement.author || '',
      authorId: announcement.authorId || '',
      important: announcement.important || false,
      attachments: announcement.attachments || [],
    };
    
    // In a real app, you would save the announcement to the database
    
    return newAnnouncement;
  },
};

// Message Service
export const messageService = {
  getMessages: async (userId: string): Promise<Message[]> => {
    await delay(800);
    
    return messages.filter(m => 
      m.sender_id === userId || m.receiver_id === userId
    );
  },
  
  sendMessage: async (message: Partial<Message>): Promise<Message> => {
    await delay(1000);
    
    const newMessage: Message = {
      id: `message_${Date.now()}`,
      sender_id: message.sender_id || '',
      sender_name: message.sender_name,
      sender_role: message.sender_role,
      receiver_id: message.receiver_id || '',
      content: message.content || '',
      timestamp: message.timestamp || new Date().toISOString(),
      read: false,
      attachments: message.attachments || [],
    };
    
    // In a real app, you would save the message to the database
    
    return newMessage;
  },
  
  markAsRead: async (messageId: string): Promise<void> => {
    await delay(500);
    
    // In a real app, you would update the message in the database
  },
};

// Schedule Service
export const scheduleService = {
  getSchedule: async (studentId: string): Promise<any[]> => {
    await delay(800);
    
    return schedule;
  },
};

// Event Service
export const eventService = {
  getEvents: async (): Promise<any[]> => {
    await delay(800);
    
    return events;
  },
  
  createEvent: async (event: any): Promise<any> => {
    await delay(1000);
    
    const newEvent = {
      id: `event_${Date.now()}`,
      ...event,
    };
    
    // In a real app, you would save the event to the database
    
    return newEvent;
  },
};

// Document Service
export const documentService = {
  fetchDocuments: async (userId: string): Promise<Document[]> => {
    await delay(800);
    
    // Mock documents
    const documents: Document[] = [
      {
        id: 'doc1',
        title: 'Report Card - Term 1',
        type: 'PDF',
        size: '2.4 MB',
        date: '2023-05-15',
        status: 'approved',
        url: 'https://example.com/documents/report-card.pdf',
        previewUrl: 'https://example.com/documents/report-card-preview.jpg',
        owner_id: userId,
        file_path: '/documents/report-card.pdf',
        file_size: 2400000,
        is_public: false,
        upload_date: '2023-05-15T10:30:00Z',
      },
      {
        id: 'doc2',
        title: 'School Calendar 2023-2024',
        type: 'PDF',
        size: '1.2 MB',
        date: '2023-04-10',
        status: 'approved',
        url: 'https://example.com/documents/calendar.pdf',
        previewUrl: 'https://example.com/documents/calendar-preview.jpg',
        owner_id: userId,
        file_path: '/documents/calendar.pdf',
        file_size: 1200000,
        is_public: true,
        upload_date: '2023-04-10T14:15:00Z',
      },
      {
        id: 'doc3',
        title: 'Permission Slip - Field Trip',
        type: 'DOCX',
        size: '350 KB',
        date: '2023-06-02',
        status: 'pending',
        url: 'https://example.com/documents/permission-slip.docx',
        previewUrl: 'https://example.com/documents/permission-slip-preview.jpg',
        owner_id: userId,
        file_path: '/documents/permission-slip.docx',
        file_size: 350000,
        is_public: false,
        upload_date: '2023-06-02T09:45:00Z',
      },
    ];
    
    return documents;
  },
  
  uploadDocument: async (document: Partial<Document>): Promise<Document> => {
    await delay(1500);
    
    const newDocument: Document = {
      id: `doc_${Date.now()}`,
      title: document.title || 'Untitled Document',
      type: document.type || 'PDF',
      size: document.size || '0 KB',
      date: document.date || new Date().toISOString().split('T')[0],
      status: 'pending',
      url: document.url || '',
      previewUrl: document.previewUrl || '',
      owner_id: document.owner_id || '',
      file_path: document.file_path || '',
      file_size: document.file_size || 0,
      is_public: document.is_public || false,
      upload_date: document.upload_date || new Date().toISOString(),
    };
    
    return newDocument;
  },
  
  deleteDocument: async (documentId: string): Promise<void> => {
    await delay(1000);
    // In a real app, you would delete the document from storage and database
  },
  
  shareDocument: async (documentId: string, recipientId: string): Promise<void> => {
    await delay(1000);
    // In a real app, you would update document permissions in the database
  },
};

// Payment Method Service
export const paymentMethodService = {
  fetchPaymentMethods: async (userId: string): Promise<PaymentMethod[]> => {
    await delay(800);
    
    // Mock payment methods
    const paymentMethods: PaymentMethod[] = [
      {
        id: 'pm1',
        type: 'visa',
        last4: '4242',
        expiry: '04/25',
        name: 'John Doe',
        is_default: true,
        user_id: userId,
      },
      {
        id: 'pm2',
        type: 'mastercard',
        last4: '5555',
        expiry: '07/26',
        name: 'John Doe',
        is_default: false,
        user_id: userId,
      },
    ];
    
    return paymentMethods;
  },
  
  addPaymentMethod: async (paymentMethod: Partial<PaymentMethod>): Promise<PaymentMethod> => {
    await delay(1500);
    
    const newPaymentMethod: PaymentMethod = {
      id: `pm_${Date.now()}`,
      type: paymentMethod.type || 'other',
      last4: paymentMethod.last4 || '0000',
      expiry: paymentMethod.expiry || '01/30',
      name: paymentMethod.name || '',
      is_default: paymentMethod.is_default || false,
      user_id: paymentMethod.user_id || '',
    };
    
    return newPaymentMethod;
  },
  
  deletePaymentMethod: async (paymentMethodId: string): Promise<void> => {
    await delay(1000);
    // In a real app, you would delete the payment method from the database
  },
  
  setDefaultPaymentMethod: async (paymentMethodId: string): Promise<void> => {
    await delay(1000);
    // In a real app, you would update the default payment method in the database
  },
};

// Fee Service
export const feeService = {
  getFeesByStudent: async (studentId: string): Promise<Fee[]> => {
    await delay(800);
    
    return fees.filter(f => f.studentId === studentId);
  },
  
  payFee: async (feeId: string, paymentMethodId: string): Promise<Fee> => {
    await delay(1500);
    
    const fee = fees.find(f => f.id === feeId);
    
    if (!fee) {
      throw new Error('Fee not found');
    }
    
    // Update fee status
    const updatedFee: Fee = {
      ...fee,
      status: 'paid',
      paymentDate: new Date().toISOString(),
      paymentMethod: paymentMethodId,
      receiptUrl: `https://example.com/receipts/receipt_${Date.now()}.pdf`,
    };
    
    // In a real app, you would save the updated fee to the database
    
    return updatedFee;
  },
};

// Bank Account Service
export const bankAccountService = {
  fetchBankAccounts: async (userId: string): Promise<BankAccount[]> => {
    await delay(800);
    
    // Mock bank accounts
    const bankAccounts: BankAccount[] = [
      {
        id: 'ba1',
        user_id: userId,
        bank_name: 'Chase Bank',
        account_number: '****5678',
        account_name: 'John Doe',
        is_default: true,
      },
      {
        id: 'ba2',
        user_id: userId,
        bank_name: 'Bank of America',
        account_number: '****9012',
        account_name: 'John Doe',
        is_default: false,
      },
    ];
    
    return bankAccounts;
  },
  
  addBankAccount: async (bankAccount: Partial<BankAccount>): Promise<BankAccount> => {
    await delay(1500);
    
    const newBankAccount: BankAccount = {
      id: `ba_${Date.now()}`,
      user_id: bankAccount.user_id || '',
      bank_name: bankAccount.bank_name || '',
      account_number: bankAccount.account_number || '',
      account_name: bankAccount.account_name || '',
      is_default: bankAccount.is_default || false,
    };
    
    return newBankAccount;
  },
  
  deleteBankAccount: async (bankAccountId: string): Promise<void> => {
    await delay(1000);
    // In a real app, you would delete the bank account from the database
  },
  
  setDefaultBankAccount: async (bankAccountId: string): Promise<void> => {
    await delay(1000);
    // In a real app, you would update the default bank account in the database
  },
};

// API Exports
export const login = authService.login;
export const logout = authService.logout;
export const register = authService.register;
export const resetPassword = authService.resetPassword;

export const getStudent = studentService.getStudent;
export const getStudentsByParent = studentService.getStudentsByParent;
export const getStudentsByTeacher = studentService.getStudentsByTeacher;
export const updateStudent = studentService.updateStudent;

export const getCourses = courseService.getCourses;
export const getCoursesByTeacher = courseService.getCoursesByTeacher;
export const getCourse = courseService.getCourse;

export const getGradesByStudent = gradeService.getGradesByStudent;
export const getGradesByCourse = gradeService.getGradesByCourse;
export const addGrade = gradeService.addGrade;
export const updateGrade = gradeService.updateGrade;

export const getAttendanceByStudent = attendanceService.getAttendanceByStudent;
export const addAttendance = attendanceService.addAttendance;
export const updateAttendance = attendanceService.updateAttendance;

export const getAssignmentsByStudent = assignmentService.getAssignmentsByStudent;
export const getAssignmentsByCourse = assignmentService.getAssignmentsByCourse;
export const submitAssignment = assignmentService.submitAssignment;
export const gradeAssignment = assignmentService.gradeAssignment;

export const getAnnouncements = announcementService.getAnnouncements;
export const createAnnouncement = announcementService.createAnnouncement;

export const fetchMessages = messageService.getMessages;
export const sendMessage = messageService.sendMessage;
export const markMessageAsRead = messageService.markAsRead;

export const getSchedule = scheduleService.getSchedule;

export const getEvents = eventService.getEvents;
export const createEvent = eventService.createEvent;

export const fetchDocuments = documentService.fetchDocuments;
export const uploadDocument = documentService.uploadDocument;
export const deleteDocument = documentService.deleteDocument;
export const shareDocument = documentService.shareDocument;

export const fetchPaymentMethods = paymentMethodService.fetchPaymentMethods;
export const addPaymentMethod = paymentMethodService.addPaymentMethod;
export const deletePaymentMethod = paymentMethodService.deletePaymentMethod;
export const setDefaultPaymentMethod = paymentMethodService.setDefaultPaymentMethod;

export const getFeesByStudent = feeService.getFeesByStudent;
export const payFee = feeService.payFee;

export const fetchBankAccounts = bankAccountService.fetchBankAccounts;
export const addBankAccount = bankAccountService.addBankAccount;
export const deleteBankAccount = bankAccountService.deleteBankAccount;
export const setDefaultBankAccount = bankAccountService.setDefaultBankAccount;