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

/**
 * §10b — Fee engine store slice
 *
 * Slim, dedicated slice for the apply/revoke endpoints in
 * server/src/controllers/finance-engine.controller.js. The CRUD list of
 * plans + discounts continues to live in `useFinanceStore`; this slice
 * only owns the engine surfaces so the provider doesn't blow up further.
 */

export type PlanApplyScope = 'student' | 'group' | 'class';
export type DiscountApplyScope = 'student' | 'group' | 'fee_group' | 'all';

interface EngineStore {
  // Student groups
  studentGroups: StudentGroup[];
  currentGroup: StudentGroup | null;
  // apply/revoke outputs we want to surface to the UI
  lastApply: null | { scope?: string; recipients?: number; created?: number; skipped?: number; applied?: number; total_amount?: number; removed?: number; re_aggregated?: number };
  error: string | null;
  busy: boolean;

  // ---- groups ----
  fetchStudentGroups: (params?: { type?: string; search?: string }) => Promise<void>;
  fetchStudentGroup: (uid: string) => Promise<StudentGroup | null>;
  createStudentGroup: (data: Partial<StudentGroup> & { auto_track_class?: boolean }) => Promise<StudentGroup | null>;
  updateStudentGroup: (uid: string, data: Partial<StudentGroup>) => Promise<StudentGroup | null>;
  deleteStudentGroup: (uid: string) => Promise<boolean>;
  addStudentGroupMembers: (
    uid: string,
    body: { mode: 'ids' | 'class' | 'all'; student_uids?: string[]; class_id?: number },
  ) => Promise<{ added: number; skipped: number; total: number } | null>;
  removeStudentGroupMember: (uid: string, student_uid: string) => Promise<boolean>;

  // ---- plan apply/revoke ----
  applyFeePlan: (
    uid: string,
    body: { scope: PlanApplyScope; scope_uid: string; academic_year?: string; due_date_offset_days?: number },
  ) => Promise<{ scope: string; recipients: number; installments_count: number; created: number; skipped: number } | null>;
  revokeFeePlan: (uid: string) => Promise<{ removed: number } | null>;

  // ---- discount apply/revoke ----
  applyDiscount: (
    uid: string,
    body: { scope?: DiscountApplyScope; scope_uid?: string; class_id?: number; academic_year?: string; cap_percent?: number },
  ) => Promise<{ applied: number; skipped: number; total_amount: number; recipients: number } | null>;
  revokeDiscount: (uid: string) => Promise<{ removed: number; re_aggregated: number } | null>;
}

export const useFinanceEngineStore = create<EngineStore>((set) => ({
  studentGroups: [],
  currentGroup: null,
  lastApply: null,
  error: null,
  busy: false,

  // ---- groups ----
  fetchStudentGroups: async (params) => {
    try {
      const qs = new URLSearchParams();
      if (params?.type) qs.set('type', params.type);
      if (params?.search) qs.set('search', params.search);
      const res = await api.get(`/fees/engine/groups?${qs.toString()}`);
      set({ studentGroups: res.data || [], error: null });
    } catch (e: any) {
      set({ error: e?.response?.data?.error || e?.message || 'Failed to load groups' });
    }
  },
  fetchStudentGroup: async (uid) => {
    try {
      const res = await api.get(`/fees/engine/groups/${uid}`);
      set({ currentGroup: res.data, error: null });
      return res.data;
    } catch (e: any) {
      set({ error: e?.response?.data?.error || e?.message || 'Failed to load group' });
      return null;
    }
  },
  createStudentGroup: async (data) => {
    set({ busy: true });
    try {
      const res = await api.post('/fees/engine/groups', data);
      set((s) => ({ studentGroups: [res.data, ...s.studentGroups], busy: false, error: null }));
      return res.data;
    } catch (e: any) {
      set({ busy: false, error: e?.response?.data?.error || e?.message || 'Failed to create group' });
      return null;
    }
  },
  updateStudentGroup: async (uid, data) => {
    set({ busy: true });
    try {
      const res = await api.patch(`/fees/engine/groups/${uid}`, data);
      set((s) => ({ studentGroups: s.studentGroups.map((g) => (g.uid === uid ? res.data : g)), busy: false, error: null }));
      return res.data;
    } catch (e: any) {
      set({ busy: false, error: e?.response?.data?.error || e?.message || 'Failed to update group' });
      return null;
    }
  },
  deleteStudentGroup: async (uid) => {
    set({ busy: true });
    try {
      await api.delete(`/fees/engine/groups/${uid}`);
      set((s) => ({ studentGroups: s.studentGroups.filter((g) => g.uid !== uid), busy: false, error: null }));
      return true;
    } catch (e: any) {
      set({ busy: false, error: e?.response?.data?.error || e?.message || 'Failed to delete group' });
      return false;
    }
  },
  addStudentGroupMembers: async (uid, body) => {
    set({ busy: true });
    try {
      const res = await api.post(`/fees/engine/groups/${uid}/members`, body);
      set({ busy: false, error: null });
      return res.data;
    } catch (e: any) {
      set({ busy: false, error: e?.response?.data?.error || e?.message || 'Failed to add members' });
      return null;
    }
  },
  removeStudentGroupMember: async (uid, student_uid) => {
    set({ busy: true });
    try {
      await api.delete(`/fees/engine/groups/${uid}/members/${student_uid}`);
      set({ busy: false, error: null });
      return true;
    } catch (e: any) {
      set({ busy: false, error: e?.response?.data?.error || e?.message || 'Failed to remove member' });
      return false;
    }
  },

  // ---- plan apply/revoke ----
  applyFeePlan: async (uid, body) => {
    set({ busy: true });
    try {
      const res = await api.post(`/fees/engine/plans/${uid}/apply`, body);
      set({ busy: false, error: null, lastApply: res.data });
      return res.data;
    } catch (e: any) {
      set({ busy: false, error: e?.response?.data?.error || e?.message || 'Failed to apply plan' });
      return null;
    }
  },
  revokeFeePlan: async (uid) => {
    set({ busy: true });
    try {
      const res = await api.post(`/fees/engine/plans/${uid}/revoke`, {});
      set({ busy: false, error: null, lastApply: res.data });
      return res.data;
    } catch (e: any) {
      set({ busy: false, error: e?.response?.data?.error || e?.message || 'Failed to revoke plan' });
      return null;
    }
  },

  // ---- discount apply/revoke ----
  applyDiscount: async (uid, body) => {
    set({ busy: true });
    try {
      const res = await api.post(`/fees/engine/discounts/${uid}/apply`, body);
      set({ busy: false, error: null, lastApply: res.data });
      return res.data;
    } catch (e: any) {
      set({ busy: false, error: e?.response?.data?.error || e?.message || 'Failed to apply discount' });
      return null;
    }
  },
  revokeDiscount: async (uid) => {
    set({ busy: true });
    try {
      const res = await api.post(`/fees/engine/discounts/${uid}/revoke`, {});
      set({ busy: false, error: null, lastApply: res.data });
      return res.data;
    } catch (e: any) {
      set({ busy: false, error: e?.response?.data?.error || e?.message || 'Failed to revoke discount' });
      return null;
    }
  },
}));

export default useFinanceEngineStore;
