export const NEWBIE_CYCLE_KEY = 'newbie';

export const TASK_ACTIVITY_TYPES = [
  'guide_opened',
  'notice_viewed',
  'map_visited',
  'course_board_opened',
  'facility_interacted',
  'public_message_sent',
  'skin_purchased',
] as const;

export type TaskActivityType = typeof TASK_ACTIVITY_TYPES[number];
export type TaskGroup = 'newbie' | 'weekly';
export type TaskProgressMode = 'count' | 'unique_target';

export interface TaskDefinition {
  id: string;
  group: TaskGroup;
  title: string;
  description: string;
  reward: number;
  target: number;
  activity?: TaskActivityType;
  progress_mode?: TaskProgressMode;
  allowed_targets?: string[];
  optional?: boolean;
  bonus?: boolean;
  sort_order: number;
}

export interface WeeklyCycle {
  key: string;
  starts_at: string;
  ends_at: string;
}

export interface TaskProgressState {
  targets?: string[];
}

export const NEWBIE_TASKS: TaskDefinition[] = [
  {
    id: 'newbie_guide',
    group: 'newbie',
    title: '翻阅新人手册',
    description: '打开新人引导，了解鲸镇的基本操作。',
    reward: 40,
    target: 1,
    activity: 'guide_opened',
    sort_order: 10,
  },
  {
    id: 'newbie_notice',
    group: 'newbie',
    title: '查看镇务公告',
    description: '在广场查看一次公告栏。',
    reward: 60,
    target: 1,
    activity: 'notice_viewed',
    sort_order: 20,
  },
  {
    id: 'newbie_work_zone',
    group: 'newbie',
    title: '探索打工区',
    description: '前往打工区，看看小镇的工作与学习入口。',
    reward: 80,
    target: 1,
    activity: 'map_visited',
    allowed_targets: ['work_zone'],
    sort_order: 30,
  },
  {
    id: 'newbie_course_board',
    group: 'newbie',
    title: '浏览课程板',
    description: '在打工区打开 Datawhale 课程看板。',
    reward: 120,
    target: 1,
    activity: 'course_board_opened',
    sort_order: 40,
  },
  {
    id: 'newbie_first_skin',
    group: 'newbie',
    title: '选择你的形象',
    description: '在鲸鱼商城购买任意一款皮肤。此任务可跳过。',
    reward: 100,
    target: 1,
    activity: 'skin_purchased',
    optional: true,
    sort_order: 50,
  },
];

export const WEEKLY_TASKS: TaskDefinition[] = [
  {
    id: 'weekly_explore',
    group: 'weekly',
    title: '海风巡游',
    description: '探索两个不同的开放地图。',
    reward: 100,
    target: 2,
    activity: 'map_visited',
    progress_mode: 'unique_target',
    allowed_targets: ['square', 'work_zone', 'whale_cafe'],
    sort_order: 10,
  },
  {
    id: 'weekly_course',
    group: 'weekly',
    title: '本周学习计划',
    description: '打开一次 Datawhale 课程看板。',
    reward: 100,
    target: 1,
    activity: 'course_board_opened',
    sort_order: 20,
  },
  {
    id: 'weekly_interact',
    group: 'weekly',
    title: '和小镇打招呼',
    description: '与两个不同的公共设施或 NPC 互动。',
    reward: 100,
    target: 2,
    activity: 'facility_interacted',
    progress_mode: 'unique_target',
    allowed_targets: ['welcome_board', 'notice_board', 'npc'],
    sort_order: 30,
  },
  {
    id: 'weekly_public_message',
    group: 'weekly',
    title: '分享此刻',
    description: '在公共频道成功发送一条消息。',
    reward: 100,
    target: 1,
    activity: 'public_message_sent',
    sort_order: 40,
  },
];

export const WEEKLY_COMPLETION_BONUS: TaskDefinition = {
  id: 'weekly_completion_bonus',
  group: 'weekly',
  title: '本周任务书结算',
  description: '完成本周全部四项任务后领取额外奖励。',
  reward: 200,
  target: 1,
  bonus: true,
  sort_order: 90,
};

export function getCurrentWeeklyCycle(now: Date = new Date()): WeeklyCycle {
  const formatter = new Intl.DateTimeFormat('en-CA', {
    timeZone: 'Asia/Shanghai',
    year: 'numeric',
    month: '2-digit',
    day: '2-digit',
  });
  const parts = Object.fromEntries(formatter.formatToParts(now)
    .filter((part) => part.type !== 'literal')
    .map((part) => [part.type, part.value]));
  const year = Number(parts.year);
  const month = Number(parts.month);
  const day = Number(parts.day);
  const chinaDateAsUtc = Date.UTC(year, month - 1, day);
  const weekday = new Date(chinaDateAsUtc).getUTCDay();
  const daysSinceMonday = (weekday + 6) % 7;
  const mondayAsUtc = chinaDateAsUtc - daysSinceMonday * 24 * 60 * 60 * 1000;
  const monday = new Date(mondayAsUtc);
  const cycleDate = monday.toISOString().slice(0, 10);
  const startsAt = new Date(mondayAsUtc - 8 * 60 * 60 * 1000);
  const endsAt = new Date(startsAt.getTime() + 7 * 24 * 60 * 60 * 1000);
  return {
    key: `weekly:${cycleDate}`,
    starts_at: startsAt.toISOString(),
    ends_at: endsAt.toISOString(),
  };
}

export function getTaskDefinitions(): TaskDefinition[] {
  return [...NEWBIE_TASKS, ...WEEKLY_TASKS, WEEKLY_COMPLETION_BONUS];
}

export function getTaskCycleKey(definition: TaskDefinition, cycle: WeeklyCycle): string {
  return definition.group === 'weekly' ? cycle.key : NEWBIE_CYCLE_KEY;
}
