import { CreateTrainingPlanDto, PlanGoal, PlanMode, TrainingPlan, trainingPlanApi } from '@/services/trainingPlanApi';
import AsyncStorage from '@react-native-async-storage/async-storage';
import { createAsyncThunk, createSlice, PayloadAction } from '@reduxjs/toolkit';



export type TrainingPlanState = {
  plans: TrainingPlan[];
  editingId?: string | null;
  draft: Omit<TrainingPlan, 'id' | 'createdAt'>;
  loading: boolean;
  error: string | null;
};

const STORAGE_KEY_LIST = '@training_plans';

function nextMondayISO(): string {
  const now = new Date();
  const day = now.getDay();
  const diff = (8 - day) % 7 || 7; // 距下周一的天数
  const next = new Date(now);
  next.setDate(now.getDate() + diff);
  next.setHours(0, 0, 0, 0);
  return next.toISOString();
}

const initialState: TrainingPlanState = {
  plans: [],
  editingId: null,
  loading: false,
  error: null,
  draft: {
    startDate: new Date(new Date().setHours(0, 0, 0, 0)).toISOString(),
    mode: 'daysOfWeek',
    daysOfWeek: [1, 3, 5],
    sessionsPerWeek: 3,
    goal: '',
    startWeightKg: undefined,
    preferredTimeOfDay: '',
    name: '',
  },
};

/**
 * 从服务器加载训练计划列表，同时支持本地缓存迁移
 */
export const loadPlans = createAsyncThunk('trainingPlan/loadPlans', async (_, { rejectWithValue }) => {
  try {
    // 尝试从服务器获取数据
    const response = await trainingPlanApi.list(1, 100); // 获取所有计划
    const plans = response.list;

    return { plans };
  } catch (error: any) {
    // 如果API调用失败，回退到本地存储
    console.warn('API调用失败，使用本地存储:', error.message);

    // 新版：列表
    const listStr = await AsyncStorage.getItem(STORAGE_KEY_LIST);
    if (listStr) {
      try {
        const plans = JSON.parse(listStr) as TrainingPlan[];
        return { plans } as { plans: TrainingPlan[] };
      } catch {
        // 解析失败则视为无数据
      }
    }

    return { plans: [] } as { plans: TrainingPlan[] };
  }
});

/**
 * 将当前 draft 保存为新计划并设为当前计划。
 */
export const saveDraftAsPlan = createAsyncThunk(
  'trainingPlan/saveDraftAsPlan',
  async (_: void, { getState, rejectWithValue }) => {
    try {
      const s = (getState() as any).trainingPlan as TrainingPlanState;
      const draft = s.draft;

      const createDto: CreateTrainingPlanDto = {
        startDate: draft.startDate,
        name: draft.name,
        mode: draft.mode,
        daysOfWeek: draft.daysOfWeek,
        sessionsPerWeek: draft.sessionsPerWeek,
        goal: draft.goal,
        startWeightKg: draft.startWeightKg,
        preferredTimeOfDay: draft.preferredTimeOfDay,
      };

      const newPlan = await trainingPlanApi.create(createDto);      

      return newPlan;
    } catch (error: any) {
      return rejectWithValue(error.message || '创建训练计划失败');
    }
  }
);

/**
 * 加载某个计划用于编辑：会写入 draft 与 editingId
 */
export const loadPlanForEdit = createAsyncThunk(
  'trainingPlan/loadPlanForEdit',
  async (id: string, { getState, rejectWithValue }) => {
    try {
      const detail = await trainingPlanApi.detail(id);
      const draft = {
        startDate: detail.startDate,
        name: detail.name,
        mode: detail.mode,
        daysOfWeek: detail.daysOfWeek,
        sessionsPerWeek: detail.sessionsPerWeek,
        goal: detail.goal as PlanGoal,
        startWeightKg: detail.startWeightKg ?? undefined,
        preferredTimeOfDay: detail.preferredTimeOfDay,
      } as TrainingPlanState['draft'];
      return { id, draft } as { id: string; draft: TrainingPlanState['draft'] };
    } catch (error: any) {
      return rejectWithValue(error.message || '加载计划详情失败');
    }
  }
);

/**
 * 使用当前 draft 更新 editingId 对应的计划
 */
export const updatePlanFromDraft = createAsyncThunk(
  'trainingPlan/updatePlanFromDraft',
  async (_: void, { getState, rejectWithValue }) => {
    try {
      const s = (getState() as any).trainingPlan as TrainingPlanState;
      if (!s.editingId) throw new Error('无有效编辑对象');
      const draft = s.draft;
      const dto: CreateTrainingPlanDto = {
        startDate: draft.startDate,
        name: draft.name,
        mode: draft.mode,
        daysOfWeek: draft.daysOfWeek,
        sessionsPerWeek: draft.sessionsPerWeek,
        goal: draft.goal,
        startWeightKg: draft.startWeightKg,
        preferredTimeOfDay: draft.preferredTimeOfDay,
      };
      const resp = await trainingPlanApi.update(s.editingId, dto);
      const updated: TrainingPlan = {
        id: resp.id,
        createdAt: resp.createdAt,
        startDate: resp.startDate,
        mode: resp.mode,
        daysOfWeek: resp.daysOfWeek,
        sessionsPerWeek: resp.sessionsPerWeek,
        goal: resp.goal as PlanGoal,
        startWeightKg: resp.startWeightKg ?? undefined,
        preferredTimeOfDay: resp.preferredTimeOfDay,
        name: resp.name,
      };
      // 更新本地 plans
      const idx = (s.plans || []).findIndex(p => p.id === updated.id);
      const nextPlans = [...(s.plans || [])];
      if (idx >= 0) nextPlans[idx] = updated; else nextPlans.push(updated);
      await AsyncStorage.setItem(STORAGE_KEY_LIST, JSON.stringify(nextPlans));
      return { plans: nextPlans } as { plans: TrainingPlan[] };
    } catch (error: any) {
      return rejectWithValue(error.message || '更新训练计划失败');
    }
  }
);

// 激活计划
export const activatePlan = createAsyncThunk(
  'trainingPlan/activatePlan',
  async (planId: string, { rejectWithValue }) => {
    try {
      await trainingPlanApi.activate(planId);
      return { id: planId } as { id: string };
    } catch (error: any) {
      return rejectWithValue(error.message || '激活训练计划失败');
    }
  }
);

/** 删除计划 */
export const deletePlan = createAsyncThunk(
  'trainingPlan/deletePlan',
  async (planId: string, { getState, rejectWithValue }) => {
    try {
      const s = (getState() as any).trainingPlan as TrainingPlanState;

      // 调用API删除
      await trainingPlanApi.delete(planId);

      // 更新本地状态
      const nextPlans = (s.plans || []).filter((p) => p.id !== planId);

      // 同时更新本地存储
      await AsyncStorage.setItem(STORAGE_KEY_LIST, JSON.stringify(nextPlans));

      return { plans: nextPlans } as { plans: TrainingPlan[] };
    } catch (error: any) {
      return rejectWithValue(error.message || '删除训练计划失败');
    }
  }
);

const trainingPlanSlice = createSlice({
  name: 'trainingPlan',
  initialState,
  reducers: {
    setMode(state, action: PayloadAction<PlanMode>) {
      state.draft.mode = action.payload;
    },
    toggleDayOfWeek(state, action: PayloadAction<number>) {
      const d = action.payload;
      const set = new Set(state.draft.daysOfWeek);
      if (set.has(d)) set.delete(d); else set.add(d);
      state.draft.daysOfWeek = Array.from(set).sort();
    },
    setSessionsPerWeek(state, action: PayloadAction<number>) {
      const n = Math.min(7, Math.max(1, action.payload));
      state.draft.sessionsPerWeek = n;
    },
    setGoal(state, action: PayloadAction<TrainingPlan['goal']>) {
      state.draft.goal = action.payload;
    },
    setStartWeight(state, action: PayloadAction<number | undefined>) {
      state.draft.startWeightKg = action.payload;
    },
    setStartDate(state, action: PayloadAction<string>) {
      state.draft.startDate = action.payload;
    },
    setPreferredTime(state, action: PayloadAction<TrainingPlan['preferredTimeOfDay']>) {
      state.draft.preferredTimeOfDay = action.payload;
    },
    setName(state, action: PayloadAction<string>) {
      state.draft.name = action.payload;
    },
    setStartDateNextMonday(state) {
      state.draft.startDate = nextMondayISO();
    },
    resetDraft(state) {
      state.draft = initialState.draft;
    },
    clearError(state) {
      state.error = null;
    },
    setEditingId(state, action: PayloadAction<string | null>) {
      state.editingId = action.payload;
    },
  },
  extraReducers: (builder) => {
    builder
      // loadPlans
      .addCase(loadPlans.pending, (state) => {
        state.loading = true;
        state.error = null;
      })
      .addCase(loadPlans.fulfilled, (state, action) => {
        state.loading = false;
        state.plans = action.payload.plans;
      })
      .addCase(loadPlans.rejected, (state, action) => {
        state.loading = false;
        state.error = action.payload as string || '加载训练计划失败';
      })
      // saveDraftAsPlan
      .addCase(saveDraftAsPlan.pending, (state) => {
        state.loading = true;
        state.error = null;
      })
      .addCase(saveDraftAsPlan.fulfilled, (state, action) => {
        state.loading = false;
      })
      .addCase(saveDraftAsPlan.rejected, (state, action) => {
        state.loading = false;
        state.error = action.payload as string || '创建训练计划失败';
      })
      // loadPlanForEdit
      .addCase(loadPlanForEdit.pending, (state) => {
        state.loading = true;
        state.error = null;
      })
      .addCase(loadPlanForEdit.fulfilled, (state, action) => {
        state.loading = false;
        state.editingId = action.payload.id;
        state.draft = action.payload.draft;
      })
      .addCase(loadPlanForEdit.rejected, (state, action) => {
        state.loading = false;
        state.error = action.payload as string || '加载计划详情失败';
      })
      // updatePlanFromDraft
      .addCase(updatePlanFromDraft.pending, (state) => {
        state.loading = true;
        state.error = null;
      })
      .addCase(updatePlanFromDraft.fulfilled, (state, action) => {
        state.loading = false;
        state.plans = action.payload.plans;
      })
      .addCase(updatePlanFromDraft.rejected, (state, action) => {
        state.loading = false;
        state.error = action.payload as string || '更新训练计划失败';
      })
      // activatePlan
      .addCase(activatePlan.pending, (state) => {
        state.loading = true;
        state.error = null;
      })
      .addCase(activatePlan.fulfilled, (state, action) => {
        state.loading = false;
      })
      .addCase(activatePlan.rejected, (state, action) => {
        state.loading = false;
        state.error = action.payload as string || '激活训练计划失败';
      })
      // deletePlan
      .addCase(deletePlan.pending, (state) => {
        state.loading = true;
        state.error = null;
      })
      .addCase(deletePlan.fulfilled, (state, action) => {
        state.loading = false;
        state.plans = action.payload.plans;
      })
      .addCase(deletePlan.rejected, (state, action) => {
        state.loading = false;
        state.error = action.payload as string || '删除训练计划失败';
      });
  },
});

export const {
  setMode,
  toggleDayOfWeek,
  setSessionsPerWeek,
  setGoal,
  setStartWeight,
  setStartDate,
  setPreferredTime,
  setName,
  setStartDateNextMonday,
  resetDraft,
  clearError,
  setEditingId,
} = trainingPlanSlice.actions;

export default trainingPlanSlice.reducer;


