import { PlayerWalletPayload } from '../player/player.types';
import { getTaskCycleKey, NEWBIE_TASKS, TaskActivityType, TaskDefinition, WEEKLY_COMPLETION_BONUS, WEEKLY_TASKS, WeeklyCycle } from './task_catalog';

export interface TaskProgressRow {
  task_id: string;
  cycle_key: string;
  progress: number;
  activity_state: Record<string, unknown>;
  completed_at: Date | null;
  claimed_at: Date | null;
}

export interface TaskPayload {
  id: string;
  title: string;
  description: string;
  reward: number;
  target: number;
  progress: number;
  optional: boolean;
  bonus: boolean;
  completed: boolean;
  claimed: boolean;
  claimable: boolean;
}

export interface TaskBoardPayload {
  weekly_cycle: WeeklyCycle;
  newbie_tasks: TaskPayload[];
  weekly_tasks: TaskPayload[];
  weekly_bonus: TaskPayload;
}

export interface TaskClaimResult {
  board: TaskBoardPayload;
  wallet: PlayerWalletPayload;
}

export interface TaskProgressStore {
  getBoard(userId: bigint): Promise<TaskBoardPayload>;
  recordActivity(userId: bigint, activity: TaskActivityType, targetId?: string): Promise<TaskBoardPayload>;
  claim(userId: bigint, taskId: string): Promise<TaskClaimResult>;
}

export function toTaskPayload(definition: TaskDefinition, row: TaskProgressRow): TaskPayload {
  const completed = row.completed_at != null;
  const claimed = row.claimed_at != null;
  return {
    id: definition.id,
    title: definition.title,
    description: definition.description,
    reward: definition.reward,
    target: definition.target,
    progress: Math.min(definition.target, Math.max(0, row.progress)),
    optional: Boolean(definition.optional),
    bonus: Boolean(definition.bonus),
    completed,
    claimed,
    claimable: completed && !claimed,
  };
}

export function buildTaskBoard(rows: TaskProgressRow[], cycle: WeeklyCycle): TaskBoardPayload {
  const rowsByKey = new Map(rows.map((row) => [`${row.task_id}:${row.cycle_key}`, row]));
  const rowFor = (definition: TaskDefinition): TaskProgressRow => {
    const row = rowsByKey.get(`${definition.id}:${getTaskCycleKey(definition, cycle)}`);
    if (!row) {
      throw new Error(`任务进度缺失: ${definition.id}`);
    }
    return row;
  };
  return {
    weekly_cycle: cycle,
    newbie_tasks: NEWBIE_TASKS.map((definition) => toTaskPayload(definition, rowFor(definition))),
    weekly_tasks: WEEKLY_TASKS.map((definition) => toTaskPayload(definition, rowFor(definition))),
    weekly_bonus: toTaskPayload(WEEKLY_COMPLETION_BONUS, rowFor(WEEKLY_COMPLETION_BONUS)),
  };
}
