import { create } from "zustand";
import type { TradeRecord, DashboardAlert } from "../types/models";

export type AgentHealthStatus = "active" | "resting" | "danger" | "bankrupt";

export interface AgentUpdate {
  type: "balance" | "trade" | "status";
  agentId: string;
  timestamp: string;
  data: unknown;
}

export interface AgentState {
  id: string;
  name: string;
  status: "running" | "paused" | "stopped" | "error";
  healthStatus: AgentHealthStatus;
  strategy: string;
  symbol: string;
  balance: number;
  profitLoss: number;
  profitLossPercent: number;
  tradesCount: number;
  winRate: number;
  lastUpdated: string;
  recentActivity?: string;
}

interface AgentStoreState {
  // Data
  agents: Record<string, AgentState>;
  recentTrades: TradeRecord[];
  alerts: DashboardAlert[];

  // Connection state
  isConnected: boolean;
  lastConnectionTime: string | null;

  // Actions
  setAgent: (agent: AgentState) => void;
  setAlerts: (alerts: DashboardAlert[]) => void;
  updateAgentBalance: (
    agentId: string,
    balance: number,
    profitLoss: number,
    profitLossPercent: number,
  ) => void;
  updateAgentStatus: (
    agentId: string,
    status: AgentState["status"],
    healthStatus: AgentHealthStatus,
  ) => void;
  addTrade: (trade: TradeRecord) => void;
  setConnectionStatus: (connected: boolean) => void;
  updateAgentHealth: (agentId: string, healthStatus: AgentHealthStatus) => void;
  getAllAgents: () => AgentState[];
  getAgentById: (id: string) => AgentState | undefined;
  clearData: () => void;
}

const MAX_TRADES_HISTORY = 100;

// Helper to determine health status based on balance and P&L
function determineHealthStatus(
  balance: number,
  profitLossPercent: number,
  status: AgentState["status"],
): AgentHealthStatus {
  if (balance < 100) return "bankrupt";
  if (profitLossPercent < -10) return "danger";
  if (status === "running") return "active";
  return "resting";
}

export const useAgentStore = create<AgentStoreState>((set, get) => ({
  // Initial state
  agents: {},
  recentTrades: [],
  alerts: [],
  isConnected: false,
  lastConnectionTime: null,

  // Actions
  setAlerts: (alerts) => set(() => ({ alerts })),

  setAgent: (agent) =>
    set((state) => {
      const healthStatus = determineHealthStatus(
        agent.balance,
        agent.profitLossPercent,
        agent.status,
      );
      return {
        agents: {
          ...state.agents,
          [agent.id]: {
            ...agent,
            healthStatus,
            lastUpdated: new Date().toISOString(),
          },
        },
      };
    }),

  updateAgentBalance: (agentId, balance, profitLoss, profitLossPercent) =>
    set((state) => {
      const agent = state.agents[agentId];
      if (!agent) return state;

      const healthStatus = determineHealthStatus(
        balance,
        profitLossPercent,
        agent.status,
      );

      return {
        agents: {
          ...state.agents,
          [agentId]: {
            ...agent,
            balance,
            profitLoss,
            profitLossPercent,
            healthStatus,
            lastUpdated: new Date().toISOString(),
            recentActivity: new Date().toISOString(),
          },
        },
      };
    }),

  updateAgentStatus: (agentId, status, healthStatus) =>
    set((state) => {
      const agent = state.agents[agentId];
      if (!agent) return state;

      return {
        agents: {
          ...state.agents,
          [agentId]: {
            ...agent,
            status,
            healthStatus,
            lastUpdated: new Date().toISOString(),
            recentActivity: new Date().toISOString(),
          },
        },
      };
    }),

  updateAgentHealth: (agentId, healthStatus) =>
    set((state) => {
      const agent = state.agents[agentId];
      if (!agent) return state;

      return {
        agents: {
          ...state.agents,
          [agentId]: {
            ...agent,
            healthStatus,
            lastUpdated: new Date().toISOString(),
          },
        },
      };
    }),

  addTrade: (trade) =>
    set((state) => {
      // Check if trade already exists
      const exists = state.recentTrades.some((t) => t.id === trade.id);
      if (exists) return state;

      // Add new trade at the beginning and limit history
      const newTrades = [trade, ...state.recentTrades].slice(
        0,
        MAX_TRADES_HISTORY,
      );

      // Update agent's trade count if agent exists
      const agent = state.agents[trade.agentId];
      const updatedAgents = agent
        ? {
            ...state.agents,
            [trade.agentId]: {
              ...agent,
              tradesCount: agent.tradesCount + 1,
              recentActivity: new Date().toISOString(),
            },
          }
        : state.agents;

      return {
        recentTrades: newTrades,
        agents: updatedAgents,
      };
    }),

  setConnectionStatus: (connected) =>
    set(() => ({
      isConnected: connected,
      lastConnectionTime: connected ? new Date().toISOString() : null,
    })),

  getAllAgents: () => {
    const state = get();
    return Object.values(state.agents);
  },

  getAgentById: (id) => {
    const state = get();
    return state.agents[id];
  },

  clearData: () =>
    set(() => ({
      agents: {},
      recentTrades: [],
      alerts: [],
      isConnected: false,
      lastConnectionTime: null,
    })),
}));
