import type { PlayerSession } from '../game/PlayerSession.js';
import { characterSetup } from '../services/character/character_manager.js';
import { Sex } from '../models/Person.js';

interface CharacterSetupPayload {
  firstname?: string;
  lastname?: string;
  name?: string;  // iOS sends full name
  age?: number;   // iOS sends starting age
  sex?: 'male' | 'female' | 'Male' | 'Female';
  skinTone?: string;
  hairColor?: string;
  hairStyle?: string;
}

export async function handleCharacterSetup(
  payload: unknown,
  session: PlayerSession
): Promise<void> {
  const data = payload as CharacterSetupPayload;
  const player = session.player;

  // Build the setup data for characterSetup function
  const setupData: { name?: string; age?: string; sex?: Sex } = {};

  // Handle name - iOS sends 'name' as full name
  if (data.name) {
    setupData.name = data.name.trim();
  } else if (data.firstname) {
    setupData.name = data.firstname + (data.lastname ? ' ' + data.lastname : '');
  }

  // Handle age
  if (data.age !== undefined) {
    setupData.age = String(data.age);
  }

  // Handle sex - normalize to expected format
  if (data.sex) {
    const normalizedSex = data.sex.charAt(0).toUpperCase() + data.sex.slice(1).toLowerCase();
    setupData.sex = normalizedSex as Sex;
  }

  // Call the characterSetup function which creates family, sets avatar, etc.
  const hasName = setupData.name;
  const hasSex = setupData.sex;

  if (hasName && hasSex) {
    characterSetup(player, setupData);

    // Start the game loop
    session.start();
  } else {
    // Partial setup - just update provided fields
    if (setupData.name) {
      const nameParts = setupData.name.split(/\s+/);
      player.c.firstname = nameParts[0] || '';
      player.c.lastname = nameParts.slice(1).join(' ') || '';
    }
    if (setupData.sex) {
      player.c.sex = setupData.sex;
    }
    if (setupData.age) {
      player.c.ageYears = parseInt(setupData.age, 10);
    }
  }

  // Send updated player object
  session.sendPlayerObject();

  // Send confirmation message
  session.send({
    type: 'characterSetupComplete',
    success: true,
    characterId: player.c.id,
  });
}

export async function handleDeviceToken(
  payload: unknown,
  session: PlayerSession
): Promise<void> {
  const token = typeof payload === 'string'
    ? payload
    : (payload as { token?: string; message?: string })?.token
      ?? (payload as { token?: string; message?: string })?.message;

  if (token) {
    session.player.deviceToken = token;
  }
}

interface LiveActivityTokenPayload {
  activityId?: string;
  token?: string;
  pushToken?: string;
  characterId?: string;
}

export async function handleLiveActivityToken(
  payload: unknown,
  session: PlayerSession
): Promise<void> {
  const data = payload as LiveActivityTokenPayload;
  const activityId = data?.activityId;
  const pushToken = data?.token ?? data?.pushToken;
  const characterId = data?.characterId;

  if (!activityId || !pushToken || !characterId || characterId !== session.player.c.id) {
    return;
  }

  session.player.liveActivity = {
    activityId,
    pushToken,
    characterId,
    startedAt: session.player.liveActivity?.activityId === activityId
      ? session.player.liveActivity.startedAt
      : new Date().toISOString(),
    lastSentAt: session.player.liveActivity?.activityId === activityId
      ? session.player.liveActivity.lastSentAt
      : undefined,
  };
}

export async function handleLiveActivityEnded(
  payload: unknown,
  session: PlayerSession
): Promise<void> {
  const data = payload as { activityId?: string };
  const activityId = data?.activityId;

  if (!activityId || session.player.liveActivity?.activityId === activityId) {
    session.player.liveActivity = undefined;
  }
}
