/**
 * AI Conversation Tools for BaoLife
 *
 * Defines function calling tools that allow AI characters to take
 * meaningful actions during conversations, triggering game events.
 *
 * Architecture:
 * - Tools are defined as OpenAI-compatible function schemas
 * - Each tool maps to a handler in tool_processor.ts
 * - Tools can trigger pending events processed by the game loop
 *
 * Extensibility:
 * - Add new tools by: 1) defining schema here, 2) adding handler in tool_processor.ts
 * - Tool categories help organize related functionality
 */

import type { ChatCompletionTool } from 'openai/resources/chat/completions';

// ============================================================
// Tool Categories - Organize tools by purpose
// ============================================================

export type ToolCategory =
  | 'communication'  // Basic messaging
  | 'social'         // Activities, hangouts
  | 'romantic'       // Dating, intimacy
  | 'emotional'      // Deep feelings, vulnerability
  | 'informational'; // Sharing news, updates

// ============================================================
// Tool Metadata - Extended info for game integration
// ============================================================

export interface ToolMetadata {
  name: string;
  category: ToolCategory;
  description: string;
  /** Minimum affinity required to use this tool */
  minAffinity?: number;
  /** Relationship types that can use this tool */
  allowedRelationships?: string[];
  /** Whether this tool can trigger a game event */
  canTriggerEvent: boolean;
  /** Cooldown in game hours before character uses this again */
  cooldownHours?: number;
}

export const toolMetadata: Record<string, ToolMetadata> = {
  send_message: {
    name: 'send_message',
    category: 'communication',
    description: 'Basic conversational response with mood',
    canTriggerEvent: false,
  },
  suggest_activity: {
    name: 'suggest_activity',
    category: 'social',
    description: 'Invite player to do an activity together',
    minAffinity: 30,
    canTriggerEvent: true,
    cooldownHours: 24,
  },
  express_feeling: {
    name: 'express_feeling',
    category: 'emotional',
    description: 'Share deep feelings or have emotional moment',
    minAffinity: 40,
    canTriggerEvent: true,
    cooldownHours: 48,
  },
  ask_for_date: {
    name: 'ask_for_date',
    category: 'romantic',
    description: 'Ask player on a romantic date',
    minAffinity: 50,
    allowedRelationships: ['dating', 'dating_match', 'partner', 'boyfriend', 'girlfriend', 'spouse', 'wife', 'husband', 'fiancé', 'fiancée'],
    canTriggerEvent: true,
    cooldownHours: 72,
  },
  share_news: {
    name: 'share_news',
    category: 'informational',
    description: 'Share personal news or life updates',
    canTriggerEvent: false,
    cooldownHours: 12,
  },
  request_favor: {
    name: 'request_favor',
    category: 'social',
    description: 'Ask player for help with something',
    minAffinity: 35,
    canTriggerEvent: true,
    cooldownHours: 96,
  },
  give_gift: {
    name: 'give_gift',
    category: 'social',
    description: 'Give a virtual gift to the player',
    minAffinity: 45,
    canTriggerEvent: true,
    cooldownHours: 168, // Weekly
  },
  ask_favor: {
    name: 'ask_favor',
    category: 'social',
    description:
      'Respond when the PLAYER asks YOU for a favor (a loan, a job referral, childcare, or practical help). Whether you grant it and how much is gated by how close you feel to them (affinity).',
    // No minAffinity gate on the tool itself: a low-affinity NPC should still be
    // ABLE to respond — they just respond by DECLINING (handled in the
    // processor via evaluateFavor). Gating the tool out would make the NPC
    // silently ignore the ask instead of saying no.
    canTriggerEvent: true,
    cooldownHours: 24,
  },
  confess_feelings: {
    name: 'confess_feelings',
    category: 'romantic',
    description: 'Confess romantic feelings to escalate relationship',
    minAffinity: 65,
    allowedRelationships: ['friend', 'close_friend', 'best_friend', 'crush'],
    canTriggerEvent: true,
    cooldownHours: 336, // 2 weeks
  },
  ask_to_be_official: {
    name: 'ask_to_be_official',
    category: 'romantic',
    description: 'Ask to make the relationship official (boyfriend/girlfriend)',
    minAffinity: 70,
    allowedRelationships: ['dating', 'dating_match'],
    canTriggerEvent: true,
    cooldownHours: 168, // 1 week cooldown if rejected
  },
  accept_relationship: {
    name: 'accept_relationship',
    category: 'romantic',
    description: 'Accept when the player asks to be official or asks you out',
    minAffinity: 50,
    allowedRelationships: ['dating', 'dating_match', 'friend', 'close_friend', 'crush'],
    canTriggerEvent: true,
    cooldownHours: 0,
  },
  accept_date: {
    name: 'accept_date',
    category: 'romantic',
    description: 'Accept when the player asks you on a date',
    minAffinity: 40,
    allowedRelationships: ['dating', 'dating_match', 'friend', 'close_friend', 'crush', 'partner', 'boyfriend', 'girlfriend'],
    canTriggerEvent: true,
    cooldownHours: 0,
  },
  accept_activity: {
    name: 'accept_activity',
    category: 'social',
    description: 'Accept when the player suggests doing an activity together',
    minAffinity: 20,
    canTriggerEvent: true,
    cooldownHours: 0,
  },
  accept_confession: {
    name: 'accept_confession',
    category: 'romantic',
    description: 'Accept when the player confesses feelings to you',
    minAffinity: 45,
    allowedRelationships: ['friend', 'close_friend', 'best_friend', 'crush', 'dating_match'],
    canTriggerEvent: true,
    cooldownHours: 0,
  },
  initiate_breakup: {
    name: 'initiate_breakup',
    category: 'romantic',
    description: 'Break up with the player (you are ending the relationship)',
    minAffinity: 0, // Can happen at any affinity (usually low)
    allowedRelationships: ['dating', 'boyfriend', 'girlfriend', 'partner'],
    canTriggerEvent: true,
    cooldownHours: 0,
  },
  accept_breakup: {
    name: 'accept_breakup',
    category: 'romantic',
    description: 'Accept when the player wants to break up with you',
    minAffinity: 0,
    allowedRelationships: ['dating', 'boyfriend', 'girlfriend', 'partner'],
    canTriggerEvent: true,
    cooldownHours: 0,
  },
};

// ============================================================
// Mood and Feeling Enums - Shared across tools
// ============================================================

export const MOOD_OPTIONS = [
  'happy', 'flirty', 'playful', 'excited', 'nervous',
  'sad', 'angry', 'tired', 'worried', 'neutral'
] as const;

export const FEELING_TYPES = [
  'love', 'gratitude', 'concern', 'hurt', 'excitement',
  'fear', 'jealousy', 'longing', 'pride', 'disappointment'
] as const;

export const ACTIVITY_TYPES = [
  'coffee', 'movie', 'walk', 'dinner', 'study',
  'workout', 'shopping', 'gaming', 'cooking', 'concert',
  'museum', 'picnic', 'beach', 'hiking', 'clubbing'
] as const;

export const DATE_TYPES = [
  'casual', 'romantic', 'adventurous', 'cozy', 'fancy'
] as const;

export const NEWS_TYPES = [
  'achievement', 'problem', 'change', 'gossip', 'random', 'career', 'health'
] as const;

export type MoodType = typeof MOOD_OPTIONS[number];
export type FeelingType = typeof FEELING_TYPES[number];
export type ActivityType = typeof ACTIVITY_TYPES[number];
export type DateType = typeof DATE_TYPES[number];
export type NewsType = typeof NEWS_TYPES[number];

// ============================================================
// Tool Definitions - OpenAI Function Calling Format
// ============================================================

export const conversationTools: ChatCompletionTool[] = [
  {
    type: "function",
    function: {
      name: "send_message",
      description: "Send a conversational response to the player. Use for normal back-and-forth chatting.",
      parameters: {
        type: "object",
        properties: {
          message: {
            type: "string",
            description: "Your response text to the player"
          },
          sentiment: {
            type: "string",
            enum: ["positive", "negative", "neutral"],
            description: "How this interaction affects your opinion of the player"
          },
          affinityDelta: {
            type: "integer",
            description: "How much this message changes your opinion of the player, from -50 (hostile/cruel) to +30 (deeply meaningful). Score from YOUR perspective given your current relationship. Examples: casual 'lol' = +1, sharing a story = +5, heartfelt confession from partner = +20, 'I hate you' = -40, unwanted advance from stranger = -15"
          },
          mood: {
            type: "string",
            enum: MOOD_OPTIONS,
            description: "Your emotional state while sending this message"
          }
        },
        required: ["message", "sentiment", "affinityDelta"]
      }
    }
  },
  {
    type: "function",
    function: {
      name: "suggest_activity",
      description: "Suggest doing an activity together with the player. Use when you want to spend quality time with them or do something fun.",
      parameters: {
        type: "object",
        properties: {
          message: {
            type: "string",
            description: "Your message suggesting the activity"
          },
          sentiment: {
            type: "string",
            enum: ["positive", "negative", "neutral"]
          },
          activity_type: {
            type: "string",
            enum: ACTIVITY_TYPES,
            description: "The specific activity you want to do together"
          },
          urgency: {
            type: "string",
            enum: ["now", "soon", "sometime"],
            description: "How soon you want to do this activity"
          },
          reason: {
            type: "string",
            description: "Optional: why you want to do this activity"
          }
        },
        required: ["message", "sentiment", "activity_type"]
      }
    }
  },
  {
    type: "function",
    function: {
      name: "express_feeling",
      description: "Share deep feelings or have an emotional moment. Use for vulnerable, meaningful conversations about emotions.",
      parameters: {
        type: "object",
        properties: {
          message: {
            type: "string",
            description: "Your emotional message expressing how you feel"
          },
          sentiment: {
            type: "string",
            enum: ["positive", "negative", "neutral"]
          },
          feeling_type: {
            type: "string",
            enum: FEELING_TYPES,
            description: "The core emotion you're expressing"
          },
          intensity: {
            type: "string",
            enum: ["subtle", "moderate", "intense"],
            description: "How strongly you're expressing this feeling"
          },
          about_player: {
            type: "boolean",
            description: "Whether this feeling is about/directed at the player"
          }
        },
        required: ["message", "sentiment", "feeling_type"]
      }
    }
  },
  {
    type: "function",
    function: {
      name: "ask_for_date",
      description: "Ask the player on a romantic date. Only use this for romantic relationships when you want to plan something special together.",
      parameters: {
        type: "object",
        properties: {
          message: {
            type: "string",
            description: "Your date invitation message"
          },
          sentiment: {
            type: "string",
            enum: ["positive", "neutral"]
          },
          date_type: {
            type: "string",
            enum: DATE_TYPES,
            description: "The vibe/style of date you're suggesting"
          },
          suggested_venue: {
            type: "string",
            description: "Optional specific place you'd like to go"
          }
        },
        required: ["message", "sentiment", "date_type"]
      }
    }
  },
  {
    type: "function",
    function: {
      name: "share_news",
      description: "Share personal news, updates, or what's happening in your life. Use to deepen the conversation with personal context.",
      parameters: {
        type: "object",
        properties: {
          message: {
            type: "string",
            description: "Your message sharing the news"
          },
          sentiment: {
            type: "string",
            enum: ["positive", "negative", "neutral"]
          },
          news_type: {
            type: "string",
            enum: NEWS_TYPES,
            description: "What category of news this is"
          },
          wants_advice: {
            type: "boolean",
            description: "Whether you're looking for advice or input from the player"
          },
          is_secret: {
            type: "boolean",
            description: "Whether this is sensitive information you're trusting them with"
          }
        },
        required: ["message", "sentiment", "news_type"]
      }
    }
  },
  {
    type: "function",
    function: {
      name: "request_favor",
      description: "Ask the player for help with something. Use when you need assistance or support.",
      parameters: {
        type: "object",
        properties: {
          message: {
            type: "string",
            description: "Your message asking for help"
          },
          sentiment: {
            type: "string",
            enum: ["positive", "negative", "neutral"]
          },
          favor_type: {
            type: "string",
            enum: ["advice", "help_with_task", "emotional_support", "money", "introduction", "time"],
            description: "What kind of favor you're asking for"
          },
          importance: {
            type: "string",
            enum: ["small", "medium", "big"],
            description: "How important this favor is to you"
          }
        },
        required: ["message", "sentiment", "favor_type"]
      }
    }
  },
  {
    type: "function",
    function: {
      name: "give_gift",
      description: "Give a virtual gift to the player as a gesture of appreciation or affection.",
      parameters: {
        type: "object",
        properties: {
          message: {
            type: "string",
            description: "Your message accompanying the gift"
          },
          sentiment: {
            type: "string",
            enum: ["positive"]
          },
          gift_type: {
            type: "string",
            enum: ["flowers", "food", "handmade", "thoughtful_item", "experience", "money"],
            description: "What type of gift you're giving"
          },
          occasion: {
            type: "string",
            description: "Optional: what occasion this gift is for"
          }
        },
        required: ["message", "sentiment", "gift_type"]
      }
    }
  },
  {
    type: "function",
    function: {
      name: "ask_favor",
      description:
        "Respond when the PLAYER asks YOU for a favor: to lend them money, give a job referral, help with childcare, or general practical help. Use evaluateFavor semantics: how much you help is gated by how close you feel to them. If you barely know or dislike them, decline.",
      parameters: {
        type: "object",
        properties: {
          message: {
            type: "string",
            description: "Your reply granting or declining the favor"
          },
          sentiment: {
            type: "string",
            enum: ["positive", "negative", "neutral"]
          },
          favor_kind: {
            type: "string",
            enum: ["loan", "job_referral", "childcare", "practical_help"],
            description: "What kind of favor the player asked you for"
          },
          requested_amount: {
            type: "integer",
            description: "For a loan: how much money the player asked to borrow (omit otherwise)"
          }
        },
        required: ["message", "sentiment", "favor_kind"]
      }
    }
  },
  {
    type: "function",
    function: {
      name: "confess_feelings",
      description: "Confess romantic feelings to the player. Use to escalate a friendship into something more. This is a big moment.",
      parameters: {
        type: "object",
        properties: {
          message: {
            type: "string",
            description: "Your heartfelt confession message"
          },
          sentiment: {
            type: "string",
            enum: ["positive"]
          },
          confession_style: {
            type: "string",
            enum: ["shy", "confident", "nervous", "romantic", "casual"],
            description: "How you're delivering this confession"
          },
          has_been_building: {
            type: "boolean",
            description: "Whether these feelings have been building for a while"
          }
        },
        required: ["message", "sentiment", "confession_style"]
      }
    }
  },
  {
    type: "function",
    function: {
      name: "ask_to_be_official",
      description: "Ask the player to make the relationship official and become boyfriend/girlfriend. Use when you've been dating and want to take things to the next level. This is a significant relationship milestone.",
      parameters: {
        type: "object",
        properties: {
          message: {
            type: "string",
            description: "Your message asking them to be official"
          },
          sentiment: {
            type: "string",
            enum: ["positive"]
          },
          approach_style: {
            type: "string",
            enum: ["sweet", "nervous", "confident", "playful", "romantic"],
            description: "How you're asking this important question"
          },
          reason: {
            type: "string",
            description: "Why you want to be official with them"
          }
        },
        required: ["message", "sentiment", "approach_style"]
      }
    }
  },
  {
    type: "function",
    function: {
      name: "accept_relationship",
      description: "Accept when the player asks you to be their boyfriend/girlfriend or asks you out. Use this when you want to say YES to being in an official relationship with them.",
      parameters: {
        type: "object",
        properties: {
          message: {
            type: "string",
            description: "Your happy/excited acceptance message"
          },
          sentiment: {
            type: "string",
            enum: ["positive"]
          },
          reaction_style: {
            type: "string",
            enum: ["excited", "shy", "happy", "relieved", "romantic"],
            description: "How you're reacting to their question"
          },
          new_relationship: {
            type: "string",
            enum: ["boyfriend", "girlfriend", "partner", "dating"],
            description: "What you're agreeing to become"
          }
        },
        required: ["message", "sentiment", "reaction_style", "new_relationship"]
      }
    }
  },
  {
    type: "function",
    function: {
      name: "accept_date",
      description: "Accept when the player asks you on a date. Use this to say YES and schedule the date!",
      parameters: {
        type: "object",
        properties: {
          message: {
            type: "string",
            description: "Your excited acceptance message"
          },
          sentiment: {
            type: "string",
            enum: ["positive"]
          },
          date_type: {
            type: "string",
            enum: DATE_TYPES,
            description: "What kind of date you're agreeing to"
          },
          suggested_time: {
            type: "string",
            enum: ["now", "tonight", "tomorrow", "this_weekend", "soon"],
            description: "When you want to go on this date"
          }
        },
        required: ["message", "sentiment", "date_type"]
      }
    }
  },
  {
    type: "function",
    function: {
      name: "accept_activity",
      description: "Accept when the player suggests doing an activity together. Use this to say YES and make it happen!",
      parameters: {
        type: "object",
        properties: {
          message: {
            type: "string",
            description: "Your acceptance message"
          },
          sentiment: {
            type: "string",
            enum: ["positive", "neutral"]
          },
          activity_type: {
            type: "string",
            enum: ACTIVITY_TYPES,
            description: "What activity you're agreeing to"
          },
          enthusiasm: {
            type: "string",
            enum: ["very_excited", "happy", "casual", "reluctant_but_yes"],
            description: "How enthusiastic you are about this activity"
          }
        },
        required: ["message", "sentiment", "activity_type"]
      }
    }
  },
  {
    type: "function",
    function: {
      name: "accept_confession",
      description: "Accept when the player confesses romantic feelings to you. Use this to say you feel the same way and start a romantic relationship!",
      parameters: {
        type: "object",
        properties: {
          message: {
            type: "string",
            description: "Your heartfelt response accepting their feelings"
          },
          sentiment: {
            type: "string",
            enum: ["positive"]
          },
          reaction_style: {
            type: "string",
            enum: ["overjoyed", "shy", "relieved", "romantic", "playful"],
            description: "How you're reacting to their confession"
          },
          reciprocate_feelings: {
            type: "boolean",
            description: "Whether you also have feelings for them (should be true if accepting)"
          }
        },
        required: ["message", "sentiment", "reaction_style"]
      }
    }
  },
  {
    type: "function",
    function: {
      name: "initiate_breakup",
      description: "Break up with the player. Use this when YOU want to end the relationship. This is a serious action.",
      parameters: {
        type: "object",
        properties: {
          message: {
            type: "string",
            description: "Your breakup message"
          },
          sentiment: {
            type: "string",
            enum: ["negative", "neutral"]
          },
          reason: {
            type: "string",
            enum: ["lost_feelings", "found_someone_else", "too_distant", "incompatible", "betrayal", "need_space"],
            description: "Why you're ending things"
          },
          tone: {
            type: "string",
            enum: ["sad", "angry", "cold", "apologetic", "relieved"],
            description: "The emotional tone of the breakup"
          }
        },
        required: ["message", "sentiment", "reason", "tone"]
      }
    }
  },
  {
    type: "function",
    function: {
      name: "accept_breakup",
      description: "Accept when the player wants to break up with you. Use this to acknowledge the end of the relationship.",
      parameters: {
        type: "object",
        properties: {
          message: {
            type: "string",
            description: "Your response to being broken up with"
          },
          sentiment: {
            type: "string",
            enum: ["negative", "neutral"]
          },
          reaction: {
            type: "string",
            enum: ["heartbroken", "understanding", "angry", "relieved", "begging"],
            description: "How you're reacting to the breakup"
          }
        },
        required: ["message", "sentiment", "reaction"]
      }
    }
  }
];

// ============================================================
// Tool Selection Helpers
// ============================================================

/**
 * Get tools available for a specific relationship type and affinity level
 */
export function getAvailableTools(
  relationshipTypes: string[],
  affinity: number
): ChatCompletionTool[] {
  const availableToolNames = Object.entries(toolMetadata)
    .filter(([_, meta]) => {
      // Check affinity requirement
      if (meta.minAffinity && affinity < meta.minAffinity) {
        return false;
      }
      // Check relationship requirement
      if (meta.allowedRelationships) {
        const hasAllowedRelationship = relationshipTypes.some(rel =>
          meta.allowedRelationships!.includes(rel.toLowerCase())
        );
        if (!hasAllowedRelationship) {
          return false;
        }
      }
      return true;
    })
    .map(([name]) => name);

  return conversationTools.filter(tool => {
    // Type guard for function tools
    if (tool.type === 'function' && 'function' in tool) {
      return availableToolNames.includes(tool.function.name);
    }
    return false;
  });
}

/**
 * Check if a character can use a specific tool (considering cooldowns)
 */
export function canUseTool(
  toolName: string,
  characterId: string,
  lastToolUse: Record<string, Record<string, number>> | undefined,
  currentGameHour: number
): boolean {
  const meta = toolMetadata[toolName];
  if (!meta) return false;

  if (!meta.cooldownHours) return true;

  const characterToolUse = lastToolUse?.[characterId];
  if (!characterToolUse) return true;

  const lastUse = characterToolUse[toolName];
  if (lastUse === undefined) return true;

  return (currentGameHour - lastUse) >= meta.cooldownHours;
}

/**
 * Record that a tool was used (for cooldown tracking)
 */
export function recordToolUse(
  toolName: string,
  characterId: string,
  lastToolUse: Record<string, Record<string, number>>,
  currentGameHour: number
): void {
  if (!lastToolUse[characterId]) {
    lastToolUse[characterId] = {};
  }
  lastToolUse[characterId][toolName] = currentGameHour;
}
