"use client";
import React, { useEffect, useState } from "react";
import {
  keyDeleteCall,
  modelAvailableCall,
  getGuardrailsList,
} from "./networking";
import { add } from "date-fns";
import {
  InformationCircleIcon,
  StatusOnlineIcon,
  TrashIcon,
  PencilAltIcon,
  RefreshIcon,
} from "@heroicons/react/outline";
import {
  keySpendLogsCall,
  PredictedSpendLogsCall,
  keyUpdateCall,
  modelInfoCall,
  regenerateKeyCall,
} from "./networking";
import {
  Badge,
  Card,
  Table,
  Grid,
  Col,
  Button,
  TableBody,
  TableCell,
  TableHead,
  TableHeaderCell,
  TableRow,
  Dialog,
  DialogPanel,
  Text,
  Title,
  Subtitle,
  Icon,
  BarChart,
  TextInput,
  Textarea,
} from "@tremor/react";
import { InfoCircleOutlined } from "@ant-design/icons";
import {
  fetchAvailableModelsForTeamOrKey,
  getModelDisplayName,
} from "./key_team_helpers/fetch_available_models_team_key";
import {
  Select as Select3,
  SelectItem,
  MultiSelect,
  MultiSelectItem,
} from "@tremor/react";
import {
  Button as Button2,
  Modal,
  Form,
  Input,
  Select as Select2,
  InputNumber,
  message,
  Select,
  Tooltip,
  DatePicker,
} from "antd";

import { CopyToClipboard } from "react-copy-to-clipboard";
import TextArea from "antd/es/input/TextArea";

const { Option } = Select;
const isLocal = process.env.NODE_ENV === "development";
const proxyBaseUrl = isLocal ? "http://localhost:4000" : null;
if (isLocal != true) {
  console.log = function () {};
}

interface EditKeyModalProps {
  visible: boolean;
  onCancel: () => void;
  token: any; // Assuming TeamType is a type representing your team object
  onSubmit: (data: FormData) => void; // Assuming FormData is the type of data to be submitted
}

interface ModelLimitModalProps {
  visible: boolean;
  onCancel: () => void;
  token: ItemData;
  onSubmit: (updatedMetadata: any) => void;
  accessToken: string;
}

// Define the props type
interface ViewKeyTableProps {
  userID: string;
  userRole: string | null;
  accessToken: string;
  selectedTeam: any | null;
  data: any[] | null;
  setData: React.Dispatch<React.SetStateAction<any[] | null>>;
  teams: any[] | null;
  premiumUser: boolean;
}

interface ItemData {
  key_alias: string | null;
  key_name: string;
  spend: string;
  max_budget: string | null;
  models: string[];
  tpm_limit: string | null;
  rpm_limit: string | null;
  token: string;
  token_id: string | null;
  id: number;
  team_id: string;
  metadata: any;
  user_id: string | null;
  expires: any;
  budget_duration: string | null;
  budget_reset_at: string | null;
  // Add any other properties that exist in the item data
}

const ViewKeyTable: React.FC<ViewKeyTableProps> = ({
  userID,
  userRole,
  accessToken,
  selectedTeam,
  data,
  setData,
  teams,
  premiumUser,
}) => {
  const [isButtonClicked, setIsButtonClicked] = useState(false);
  const [isDeleteModalOpen, setIsDeleteModalOpen] = useState(false);
  const [keyToDelete, setKeyToDelete] = useState<string | null>(null);
  const [selectedItem, setSelectedItem] = useState<ItemData | null>(null);
  const [spendData, setSpendData] = useState<
    { day: string; spend: number }[] | null
  >(null);
  const [predictedSpendString, setPredictedSpendString] = useState("");

  const [editModalVisible, setEditModalVisible] = useState(false);
  const [infoDialogVisible, setInfoDialogVisible] = useState(false);
  const [selectedToken, setSelectedToken] = useState<ItemData | null>(null);
  const [userModels, setUserModels] = useState<string[]>([]);
  const initialKnownTeamIDs: Set<string> = new Set();
  const [modelLimitModalVisible, setModelLimitModalVisible] = useState(false);
  const [regenerateDialogVisible, setRegenerateDialogVisible] = useState(false);
  const [regeneratedKey, setRegeneratedKey] = useState<string | null>(null);
  const [regenerateFormData, setRegenerateFormData] = useState<any>(null);
  const [regenerateForm] = Form.useForm();
  const [newExpiryTime, setNewExpiryTime] = useState<string | null>(null);

  const [knownTeamIDs, setKnownTeamIDs] = useState(initialKnownTeamIDs);
  const [guardrailsList, setGuardrailsList] = useState<string[]>([]);

  // Function to check if user is admin of a team
  const isUserTeamAdmin = (team: any) => {
    if (!team.members_with_roles) return false;
    return team.members_with_roles.some(
      (member: any) => member.role === "admin" && member.user_id === userID
    );
  };

  // Combine all keys that user should have access to
  const all_keys_to_display = React.useMemo(() => {
    let allKeys: any[] = [];

    // If no teams, return personal keys
    if (!teams || teams.length === 0) {
      return data;
    }

    teams.forEach((team) => {
      // For default team or when user is not admin, use personal keys (data)
      if (team.team_id === "default-team" || !isUserTeamAdmin(team)) {
        if (selectedTeam && selectedTeam.team_id === team.team_id && data) {
          allKeys = [
            ...allKeys,
            ...data.filter((key) => key.team_id === team.team_id),
          ];
        }
      }
      // For teams where user is admin, use team keys
      else if (isUserTeamAdmin(team)) {
        if (selectedTeam && selectedTeam.team_id === team.team_id) {
          allKeys = [
            ...allKeys,
            ...(data?.filter((key) => key?.team_id === team?.team_id) || []),
          ];
        }
      }
    });

    // If no team is selected, show all accessible keys
    if ((!selectedTeam || selectedTeam.team_alias === "Default Team") && data) {
      const personalKeys = data.filter(
        (key) => !key.team_id || key.team_id === "default-team"
      );
      const adminTeamKeys = teams
        .filter((team) => isUserTeamAdmin(team))
        .flatMap((team) => team.keys || []);
      allKeys = [...personalKeys, ...adminTeamKeys];
    }

    // Filter out litellm-dashboard keys
    allKeys = allKeys.filter((key) => key.team_id !== "litellm-dashboard");

    // Remove duplicates based on token
    const uniqueKeys = Array.from(
      new Map(allKeys.map((key) => [key.token, key])).values()
    );

    return uniqueKeys;
  }, [data, teams, selectedTeam, userID]);

  useEffect(() => {
    const calculateNewExpiryTime = (duration: string | undefined) => {
      if (!duration) {
        return null;
      }

      try {
        const now = new Date();
        let newExpiry: Date;

        if (duration.endsWith("s")) {
          newExpiry = add(now, { seconds: parseInt(duration) });
        } else if (duration.endsWith("h")) {
          newExpiry = add(now, { hours: parseInt(duration) });
        } else if (duration.endsWith("d")) {
          newExpiry = add(now, { days: parseInt(duration) });
        } else {
          throw new Error("Invalid duration format");
        }

        return newExpiry.toLocaleString("en-US", {
          year: "numeric",
          month: "numeric",
          day: "numeric",
          hour: "numeric",
          minute: "numeric",
          second: "numeric",
          hour12: true,
        });
      } catch (error) {
        return null;
      }
    };

    console.log("in calculateNewExpiryTime for selectedToken", selectedToken);

    // When a new duration is entered
    if (regenerateFormData?.duration) {
      setNewExpiryTime(calculateNewExpiryTime(regenerateFormData.duration));
    } else {
      setNewExpiryTime(null);
    }

    console.log("calculateNewExpiryTime:", newExpiryTime);
  }, [selectedToken, regenerateFormData?.duration]);

  useEffect(() => {
    const fetchUserModels = async () => {
      try {
        if (userID === null || userRole === null || accessToken === null) {
          return;
        }

        const models = await fetchAvailableModelsForTeamOrKey(
          userID,
          userRole,
          accessToken
        );
        if (models) {
          setUserModels(models);
        }
      } catch (error) {
        console.error("Error fetching user models:", error);
      }
    };

    fetchUserModels();
  }, [accessToken, userID, userRole]);

  const handleModelLimitClick = (token: ItemData) => {
    setSelectedToken(token);
    setModelLimitModalVisible(true);
  };

  const handleModelLimitSubmit = async (updatedMetadata: any) => {
    if (accessToken == null || selectedToken == null) {
      return;
    }

    const formValues = {
      ...selectedToken,
      metadata: updatedMetadata,
      key: selectedToken.token,
    };

    try {
      let newKeyValues = await keyUpdateCall(accessToken, formValues);
      console.log("Model limits updated:", newKeyValues);

      // Update the keys with the updated key
      if (data) {
        const updatedData = data.map((key) =>
          key.token === selectedToken.token ? newKeyValues : key
        );
        setData(updatedData);
      }
      message.success("Model-specific limits updated successfully");
    } catch (error) {
      console.error("Error updating model-specific limits:", error);
      message.error("Failed to update model-specific limits");
    }

    setModelLimitModalVisible(false);
    setSelectedToken(null);
  };

  useEffect(() => {
    if (teams) {
      const teamIDSet: Set<string> = new Set();
      teams.forEach((team: any, index: number) => {
        const team_obj: string = team.team_id;
        teamIDSet.add(team_obj);
      });
      setKnownTeamIDs(teamIDSet);
    }
  }, [teams]);
  const EditKeyModal: React.FC<EditKeyModalProps> = ({
    visible,
    onCancel,
    token,
    onSubmit,
  }) => {
    const [form] = Form.useForm();
    const [keyTeam, setKeyTeam] = useState(selectedTeam);
    const [errorModels, setErrorModels] = useState<string[]>([]);
    const [errorBudget, setErrorBudget] = useState<boolean>(false);
    const [guardrailsList, setGuardrailsList] = useState<string[]>([]);

    useEffect(() => {
      const fetchGuardrails = async () => {
        try {
          const response = await getGuardrailsList(accessToken);
          const guardrailNames = response.guardrails.map(
            (g: { guardrail_name: string }) => g.guardrail_name
          );
          setGuardrailsList(guardrailNames);
        } catch (error) {
          console.error("Failed to fetch guardrails:", error);
        }
      };

      fetchGuardrails();
    }, [accessToken]);

    let metadataString = "";
    try {
      // Create a copy of metadata without guardrails for display
      const displayMetadata = { ...token.metadata };
      delete displayMetadata.guardrails;
      metadataString = JSON.stringify(displayMetadata, null, 2);
    } catch (error) {
      console.error("Error stringifying metadata:", error);
      metadataString = "";
    }

    // Extract existing guardrails from metadata
    let existingGuardrails: string[] = [];
    try {
      existingGuardrails = token.metadata?.guardrails || [];
    } catch (error) {
      console.error("Error extracting guardrails:", error);
    }

    const initialValues =
      token ?
        {
          ...token,
          budget_duration: token.budget_duration,
          metadata: metadataString,
          guardrails: existingGuardrails,
        }
      : { metadata: metadataString, guardrails: [] };

    const handleOk = () => {
      form
        .validateFields()
        .then((values) => {
          // const updatedValues = {...values, team_id: team.team_id};
          // onSubmit(updatedValues);
          form.resetFields();
        })
        .catch((error) => {
          console.error("Validation failed:", error);
        });
    };

    return (
      <Modal
        title="Edit Key"
        visible={visible}
        width={800}
        footer={null}
        onOk={handleOk}
        onCancel={onCancel}
      >
        <Form
          form={form}
          onFinish={handleEditSubmit}
          initialValues={initialValues}
          labelCol={{ span: 8 }}
          wrapperCol={{ span: 16 }}
          labelAlign="left"
        >
          <>
            <Form.Item name="key_alias" label="Key Alias">
              <TextInput />
            </Form.Item>

            <Form.Item
              label="Models"
              name="models"
              rules={[
                {
                  validator: (rule, value) => {
                    if (keyTeam.team_alias === "Default Team") {
                      return Promise.resolve();
                    }

                    const errorModels = value.filter(
                      (model: string) =>
                        !keyTeam.models.includes(model) &&
                        model !== "all-team-models" &&
                        model !== "all-proxy-models" &&
                        !keyTeam.models.includes("all-proxy-models")
                    );
                    console.log(`errorModels: ${errorModels}`);
                    if (errorModels.length > 0) {
                      return Promise.reject(
                        `Some models are not part of the new team's models - ${errorModels} Team models: ${keyTeam.models}`
                      );
                    } else {
                      return Promise.resolve();
                    }
                  },
                },
              ]}
            >
              <Select
                mode="multiple"
                placeholder="Select models"
                style={{ width: "100%" }}
              >
                <Option key="all-team-models" value="all-team-models">
                  All Team Models
                </Option>
                {keyTeam.team_alias === "Default Team" ?
                  userModels
                    .filter((model) => model !== "all-proxy-models")
                    .map((model: string) => (
                      <Option key={model} value={model}>
                        {getModelDisplayName(model)}
                      </Option>
                    ))
                : keyTeam.models.map((model: string) => (
                    <Option key={model} value={model}>
                      {getModelDisplayName(model)}
                    </Option>
                  ))
                }
              </Select>
            </Form.Item>
            <Form.Item
              className="mt-8"
              label="Max Budget (USD)"
              name="max_budget"
              help={`Budget cannot exceed team max budget: ${keyTeam?.max_budget !== null && keyTeam?.max_budget !== undefined ? keyTeam?.max_budget : "unlimited"}`}
              rules={[
                {
                  validator: async (_, value) => {
                    if (
                      value &&
                      keyTeam &&
                      keyTeam.max_budget !== null &&
                      value > keyTeam.max_budget
                    ) {
                      console.log(`keyTeam.max_budget: ${keyTeam.max_budget}`);
                      throw new Error(
                        `Budget cannot exceed team max budget: $${keyTeam.max_budget}`
                      );
                    }
                  },
                },
              ]}
            >
              <InputNumber step={0.01} precision={2} width={200} />
            </Form.Item>

            <Form.Item
              className="mt-8"
              label="Reset Budget"
              name="budget_duration"
              help={`Current Reset Budget: ${
                token.budget_duration
              }, budget will be reset: ${token.budget_reset_at ? new Date(token.budget_reset_at).toLocaleString() : "Never"}`}
            >
              <Select placeholder="n/a">
                <Select.Option value="daily">daily</Select.Option>
                <Select.Option value="weekly">weekly</Select.Option>
                <Select.Option value="monthly">monthly</Select.Option>
              </Select>
            </Form.Item>

            <Form.Item label="token" name="token" hidden={true}></Form.Item>
            <Form.Item
              label="Team"
              name="team_id"
              className="mt-8"
              help="the team this key belongs to"
            >
              <Select3 value={token.team_alias}>
                {teams?.map((team_obj, index) => (
                  <SelectItem
                    key={index}
                    value={team_obj.team_id}
                    onClick={() => setKeyTeam(team_obj)}
                  >
                    {team_obj.team_alias}
                  </SelectItem>
                ))}
              </Select3>
            </Form.Item>

            <Form.Item
              className="mt-8"
              label="TPM Limit (tokens per minute)"
              name="tpm_limit"
              help={`tpm_limit cannot exceed team tpm_limit ${keyTeam?.tpm_limit !== null && keyTeam?.tpm_limit !== undefined ? keyTeam?.tpm_limit : "unlimited"}`}
              rules={[
                {
                  validator: async (_, value) => {
                    if (
                      value &&
                      keyTeam &&
                      keyTeam.tpm_limit !== null &&
                      value > keyTeam.tpm_limit
                    ) {
                      console.log(`keyTeam.tpm_limit: ${keyTeam.tpm_limit}`);
                      throw new Error(
                        `tpm_limit cannot exceed team max tpm_limit: $${keyTeam.tpm_limit}`
                      );
                    }
                  },
                },
              ]}
            >
              <InputNumber step={1} precision={1} width={200} />
            </Form.Item>
            <Form.Item
              className="mt-8"
              label="RPM Limit (requests per minute)"
              name="rpm_limit"
              help={`rpm_limit cannot exceed team max rpm_limit: ${keyTeam?.rpm_limit !== null && keyTeam?.rpm_limit !== undefined ? keyTeam?.rpm_limit : "unlimited"}`}
              rules={[
                {
                  validator: async (_, value) => {
                    if (
                      value &&
                      keyTeam &&
                      keyTeam.rpm_limit !== null &&
                      value > keyTeam.rpm_limit
                    ) {
                      console.log(`keyTeam.rpm_limit: ${keyTeam.rpm_limit}`);
                      throw new Error(
                        `rpm_limit cannot exceed team max rpm_limit: $${keyTeam.rpm_limit}`
                      );
                    }
                  },
                },
              ]}
            >
              <InputNumber step={1} precision={1} width={200} />
            </Form.Item>
            <Form.Item
              label={
                <span>
                  Guardrails{" "}
                  <Tooltip title="Setup your first guardrail">
                    <a
                      href="https://docs.litellm.ai/docs/proxy/guardrails/quick_start"
                      target="_blank"
                      rel="noopener noreferrer"
                      onClick={(e) => e.stopPropagation()}
                    >
                      <InfoCircleOutlined style={{ marginLeft: "4px" }} />
                    </a>
                  </Tooltip>
                </span>
              }
              name="guardrails"
              className="mt-8"
              help="Select existing guardrails or enter new ones"
            >
              <Select
                mode="tags"
                style={{ width: "100%" }}
                placeholder="Select or enter guardrails"
                options={guardrailsList.map((name) => ({
                  value: name,
                  label: name,
                }))}
              />
            </Form.Item>
            <Form.Item
              label="Metadata (ensure this is valid JSON)"
              name="metadata"
            >
              <TextArea
                rows={10}
                onChange={(e) => {
                  form.setFieldsValue({ metadata: e.target.value });
                }}
              />
            </Form.Item>
          </>
          <div style={{ textAlign: "right", marginTop: "10px" }}>
            <Button2 htmlType="submit">Edit Key</Button2>
          </div>
        </Form>
      </Modal>
    );
  };

  const ModelLimitModal: React.FC<ModelLimitModalProps> = ({
    visible,
    onCancel,
    token,
    onSubmit,
    accessToken,
  }) => {
    const [modelLimits, setModelLimits] = useState<{
      [key: string]: { tpm: number; rpm: number };
    }>({});
    const [availableModels, setAvailableModels] = useState<string[]>([]);
    const [newModelRow, setNewModelRow] = useState<string | null>(null);

    useEffect(() => {
      if (token.metadata) {
        const tpmLimits = token.metadata.model_tpm_limit || {};
        const rpmLimits = token.metadata.model_rpm_limit || {};
        const combinedLimits: { [key: string]: { tpm: number; rpm: number } } =
          {};

        Object.keys({ ...tpmLimits, ...rpmLimits }).forEach((model) => {
          combinedLimits[model] = {
            tpm: tpmLimits[model] || 0,
            rpm: rpmLimits[model] || 0,
          };
        });

        setModelLimits(combinedLimits);
      }

      const fetchAvailableModels = async () => {
        try {
          const modelDataResponse = await modelInfoCall(accessToken, "", "");
          const allModelGroups: string[] = Array.from(
            new Set(
              modelDataResponse.data.map((model: any) => model.model_name)
            )
          );
          setAvailableModels(allModelGroups);
        } catch (error) {
          console.error("Error fetching model data:", error);
          message.error("Failed to fetch available models");
        }
      };

      fetchAvailableModels();
    }, [token, accessToken]);

    const handleLimitChange = (
      model: string,
      type: "tpm" | "rpm",
      value: number | null
    ) => {
      setModelLimits((prev) => ({
        ...prev,
        [model]: {
          ...prev[model],
          [type]: value || 0,
        },
      }));
    };

    const handleAddLimit = () => {
      setNewModelRow("");
    };

    const handleModelSelect = (model: string) => {
      if (!modelLimits[model]) {
        setModelLimits((prev) => ({
          ...prev,
          [model]: { tpm: 0, rpm: 0 },
        }));
      }
      setNewModelRow(null);
    };

    const handleRemoveModel = (model: string) => {
      setModelLimits((prev) => {
        const { [model]: _, ...rest } = prev;
        return rest;
      });
    };

    const handleSubmit = () => {
      const updatedMetadata = {
        ...token.metadata,
        model_tpm_limit: Object.fromEntries(
          Object.entries(modelLimits).map(([model, limits]) => [
            model,
            limits.tpm,
          ])
        ),
        model_rpm_limit: Object.fromEntries(
          Object.entries(modelLimits).map(([model, limits]) => [
            model,
            limits.rpm,
          ])
        ),
      };
      onSubmit(updatedMetadata);
    };

    return (
      <Modal
        title="Edit Model-Specific Limits"
        visible={visible}
        onCancel={onCancel}
        footer={null}
        width={800}
      >
        <div className="space-y-4">
          <Table>
            <TableHead>
              <TableRow>
                <TableHeaderCell>Model</TableHeaderCell>
                <TableHeaderCell>TPM Limit</TableHeaderCell>
                <TableHeaderCell>RPM Limit</TableHeaderCell>
                <TableHeaderCell>Actions</TableHeaderCell>
              </TableRow>
            </TableHead>
            <TableBody>
              {Object.entries(modelLimits).map(([model, limits]) => (
                <TableRow key={model}>
                  <TableCell>{model}</TableCell>
                  <TableCell>
                    <InputNumber
                      value={limits.tpm}
                      onChange={(value) =>
                        handleLimitChange(model, "tpm", value)
                      }
                    />
                  </TableCell>
                  <TableCell>
                    <InputNumber
                      value={limits.rpm}
                      onChange={(value) =>
                        handleLimitChange(model, "rpm", value)
                      }
                    />
                  </TableCell>
                  <TableCell>
                    <Button onClick={() => handleRemoveModel(model)}>
                      Remove
                    </Button>
                  </TableCell>
                </TableRow>
              ))}
              {newModelRow !== null && (
                <TableRow>
                  <TableCell>
                    <Select
                      style={{ width: 200 }}
                      placeholder="Select a model"
                      onChange={handleModelSelect}
                      value={newModelRow || undefined}
                    >
                      {availableModels
                        .filter((m) => !modelLimits.hasOwnProperty(m))
                        .map((m) => (
                          <Option key={m} value={m}>
                            {m}
                          </Option>
                        ))}
                    </Select>
                  </TableCell>
                  <TableCell>-</TableCell>
                  <TableCell>-</TableCell>
                  <TableCell>
                    <Button onClick={() => setNewModelRow(null)}>Cancel</Button>
                  </TableCell>
                </TableRow>
              )}
            </TableBody>
          </Table>
          <Button onClick={handleAddLimit} disabled={newModelRow !== null}>
            Add Limit
          </Button>
        </div>
        <div className="flex justify-end space-x-4 mt-6">
          <Button onClick={onCancel}>Cancel</Button>
          <Button onClick={handleSubmit}>Save</Button>
        </div>
      </Modal>
    );
  };

  const handleEditClick = (token: any) => {
    console.log("handleEditClick:", token);

    // set token.token to token.token_id if token_id is not null
    if (token.token == null) {
      if (token.token_id !== null) {
        token.token = token.token_id;
      }
    }

    // Convert the budget_duration to the corresponding select option
    let budgetDuration = null;
    if (token.budget_duration) {
      switch (token.budget_duration) {
        case "24h":
          budgetDuration = "daily";
          break;
        case "7d":
          budgetDuration = "weekly";
          break;
        case "30d":
          budgetDuration = "monthly";
          break;
        default:
          budgetDuration = "None";
      }
    }

    setSelectedToken({
      ...token,
      budget_duration: budgetDuration,
    });

    //setSelectedToken(token);
    setEditModalVisible(true);
  };

  const handleEditCancel = () => {
    setEditModalVisible(false);
    setSelectedToken(null);
  };

  const handleEditSubmit = async (formValues: Record<string, any>) => {
    /**
     * Call API to update team with teamId and values
     *
     * Client-side validation: For selected team, ensure models in team + max budget < team max budget
     */
    if (accessToken == null) {
      return;
    }

    const currentKey = formValues.token;
    formValues.key = currentKey;

    // Convert metadata back to an object if it exists and is a string
    if (formValues.metadata && typeof formValues.metadata === "string") {
      try {
        const parsedMetadata = JSON.parse(formValues.metadata);
        // Only add guardrails if they are set in form values
        formValues.metadata = {
          ...parsedMetadata,
          ...(formValues.guardrails?.length > 0 ?
            { guardrails: formValues.guardrails }
          : {}),
        };
      } catch (error) {
        console.error("Error parsing metadata JSON:", error);
        message.error(
          "Invalid metadata JSON for formValue " + formValues.metadata
        );
        return;
      }
    } else {
      // If metadata is not a string (or doesn't exist), only add guardrails if they are set
      formValues.metadata = {
        ...(formValues.metadata || {}),
        ...(formValues.guardrails?.length > 0 ?
          { guardrails: formValues.guardrails }
        : {}),
      };
    }

    // Convert the budget_duration back to the API expected format
    if (formValues.budget_duration) {
      switch (formValues.budget_duration) {
        case "daily":
          formValues.budget_duration = "24h";
          break;
        case "weekly":
          formValues.budget_duration = "7d";
          break;
        case "monthly":
          formValues.budget_duration = "30d";
          break;
      }
    }

    console.log("handleEditSubmit:", formValues);

    try {
      let newKeyValues = await keyUpdateCall(accessToken, formValues);
      console.log("handleEditSubmit: newKeyValues", newKeyValues);

      // Update the keys with the update key
      if (data) {
        const updatedData = data.map((key) =>
          key.token === currentKey ? newKeyValues : key
        );
        setData(updatedData);
      }
      message.success("Key updated successfully");

      setEditModalVisible(false);
      setSelectedToken(null);
    } catch (error) {
      console.error("Error updating key:", error);
      message.error("Failed to update key");
    }
  };

  const handleDelete = async (token: any) => {
    console.log("handleDelete:", token);
    if (token.token == null) {
      if (token.token_id !== null) {
        token.token = token.token_id;
      }
    }
    if (data == null) {
      return;
    }

    // Set the key to delete and open the confirmation modal
    setKeyToDelete(token.token);
    localStorage.removeItem("userData" + userID);
    setIsDeleteModalOpen(true);
  };

  const confirmDelete = async () => {
    if (keyToDelete == null || data == null) {
      return;
    }

    try {
      await keyDeleteCall(accessToken, keyToDelete);
      // Successfully completed the deletion. Update the state to trigger a rerender.
      const filteredData = data.filter((item) => item.token !== keyToDelete);
      setData(filteredData);
    } catch (error) {
      console.error("Error deleting the key:", error);
      // Handle any error situations, such as displaying an error message to the user.
    }

    // Close the confirmation modal and reset the keyToDelete
    setIsDeleteModalOpen(false);
    setKeyToDelete(null);
  };

  const cancelDelete = () => {
    // Close the confirmation modal and reset the keyToDelete
    setIsDeleteModalOpen(false);
    setKeyToDelete(null);
  };

  const handleRegenerateClick = (token: any) => {
    setSelectedToken(token);
    setNewExpiryTime(null);
    regenerateForm.setFieldsValue({
      key_alias: token.key_alias,
      max_budget: token.max_budget,
      tpm_limit: token.tpm_limit,
      rpm_limit: token.rpm_limit,
      duration: token.duration || "",
    });
    setRegenerateDialogVisible(true);
  };

  const handleRegenerateFormChange = (field: string, value: any) => {
    setRegenerateFormData((prev: any) => ({
      ...prev,
      [field]: value,
    }));
  };

  const handleRegenerateKey = async () => {
    if (!premiumUser) {
      message.error(
        "Regenerate API Key is an Enterprise feature. Please upgrade to use this feature."
      );
      return;
    }

    if (selectedToken == null) {
      return;
    }

    try {
      const formValues = await regenerateForm.validateFields();
      const response = await regenerateKeyCall(
        accessToken,
        selectedToken.token,
        formValues
      );
      setRegeneratedKey(response.key);

      // Update the data state with the new key_name
      if (data) {
        const updatedData = data.map((item) =>
          item.token === selectedToken?.token ?
            { ...item, key_name: response.key_name, ...formValues }
          : item
        );
        setData(updatedData);
      }

      setRegenerateDialogVisible(false);
      regenerateForm.resetFields();
      message.success("API Key regenerated successfully");
    } catch (error) {
      console.error("Error regenerating key:", error);
      message.error("Failed to regenerate API Key");
    }
  };

  if (data == null) {
    return;
  }
  console.log("RERENDER TRIGGERED");
  return (
    <div>
      <Card className="w-full mx-auto flex-auto overflow-y-auto max-h-[50vh] mb-4 mt-2">
        <Table className="mt-5 max-h-[300px] min-h-[300px]">
          <TableHead>
            <TableRow>
              <TableHeaderCell>Key Alias</TableHeaderCell>
              <TableHeaderCell>Secret Key</TableHeaderCell>
              <TableHeaderCell>Created</TableHeaderCell>
              <TableHeaderCell>Expires</TableHeaderCell>
              <TableHeaderCell>Spend (USD)</TableHeaderCell>
              <TableHeaderCell>Budget (USD)</TableHeaderCell>
              <TableHeaderCell>Budget Reset</TableHeaderCell>
              <TableHeaderCell>Models</TableHeaderCell>
              <TableHeaderCell>Rate Limits</TableHeaderCell>
              <TableHeaderCell>Rate Limits per model</TableHeaderCell>
            </TableRow>
          </TableHead>
          <TableBody>
            {all_keys_to_display &&
              all_keys_to_display.map((item) => {
                console.log(item);
                // skip item if item.team_id == "litellm-dashboard"
                if (item.team_id === "litellm-dashboard") {
                  return null;
                }
                if (selectedTeam) {
                  /**
                   * if selected team id is null -> show the keys with no team id or team id's that don't exist in db
                   */
                  console.log(
                    `item team id: ${item.team_id}, knownTeamIDs.has(item.team_id): ${knownTeamIDs.has(item.team_id)}, selectedTeam id: ${selectedTeam.team_id}`
                  );
                  if (
                    selectedTeam.team_id == null &&
                    item.team_id !== null &&
                    !knownTeamIDs.has(item.team_id)
                  ) {
                    // do nothing -> returns a row with this key
                  } else if (item.team_id != selectedTeam.team_id) {
                    return null;
                  }
                  console.log(`item team id: ${item.team_id}, is returned`);
                }
                return (
                  <TableRow key={item.token}>
                    <TableCell
                      style={{
                        maxWidth: "2px",
                        whiteSpace: "pre-wrap",
                        overflow: "hidden",
                      }}
                    >
                      {item.key_alias != null ?
                        <Text>{item.key_alias}</Text>
                      : <Text>Not Set</Text>}
                    </TableCell>
                    <TableCell>
                      <Text>{item.key_name}</Text>
                    </TableCell>
                    <TableCell>
                      {item.created_at != null ?
                        <div>
                          <p style={{ fontSize: "0.70rem" }}>
                            {new Date(item.created_at).toLocaleDateString()}
                          </p>
                        </div>
                      : <p style={{ fontSize: "0.70rem" }}>Not available</p>}
                    </TableCell>
                    <TableCell>
                      {item.expires != null ?
                        <div>
                          <p style={{ fontSize: "0.70rem" }}>
                            {new Date(item.expires).toLocaleDateString()}
                          </p>
                        </div>
                      : <p style={{ fontSize: "0.70rem" }}>Never</p>}
                    </TableCell>
                    <TableCell>
                      <Text>
                        {(() => {
                          try {
                            return parseFloat(item.spend).toFixed(4);
                          } catch (error) {
                            return item.spend;
                          }
                        })()}
                      </Text>
                    </TableCell>
                    <TableCell>
                      {item.max_budget != null ?
                        <Text>{item.max_budget}</Text>
                      : <Text>Unlimited</Text>}
                    </TableCell>
                    <TableCell>
                      {item.budget_reset_at != null ?
                        <div>
                          <p style={{ fontSize: "0.70rem" }}>
                            {new Date(item.budget_reset_at).toLocaleString()}
                          </p>
                        </div>
                      : <p style={{ fontSize: "0.70rem" }}>Never</p>}
                    </TableCell>
                    {/* <TableCell style={{ maxWidth: '2px' }}>
                  <ViewKeySpendReport
                    token={item.token}
                    accessToken={accessToken}
                    keySpend={item.spend}
                    keyBudget={item.max_budget}
                    keyName={item.key_name}
                  />
                </TableCell> */}
                    {/* <TableCell style={{ maxWidth: "4px", whiteSpace: "pre-wrap", overflow: "hidden"  }}>
                  <Text>{item.team_alias && item.team_alias != "None" ? item.team_alias : item.team_id}</Text>
                </TableCell> */}
                    {/* <TableCell style={{ maxWidth: "4px", whiteSpace: "pre-wrap", overflow: "hidden"  }}>
                  <Text>{JSON.stringify(item.metadata).slice(0, 400)}</Text>
                  
                </TableCell> */}

                    <TableCell>
                      {Array.isArray(item.models) ?
                        <div
                          style={{ display: "flex", flexDirection: "column" }}
                        >
                          {item.models.length === 0 ?
                            <>
                              {
                                (
                                  selectedTeam &&
                                  selectedTeam.models &&
                                  selectedTeam.models.length > 0
                                ) ?
                                  selectedTeam.models.map(
                                    (model: string, index: number) =>
                                      model === "all-proxy-models" ?
                                        <Badge
                                          key={index}
                                          size={"xs"}
                                          className="mb-1"
                                          color="red"
                                        >
                                          <Text>All Proxy Models</Text>
                                        </Badge>
                                      : model === "all-team-models" ?
                                        <Badge
                                          key={index}
                                          size={"xs"}
                                          className="mb-1"
                                          color="red"
                                        >
                                          <Text>All Team Models</Text>
                                        </Badge>
                                      : <Badge
                                          key={index}
                                          size={"xs"}
                                          className="mb-1"
                                          color="blue"
                                        >
                                          <Text>
                                            {model.length > 30 ?
                                              `${getModelDisplayName(model).slice(0, 30)}...`
                                            : getModelDisplayName(model)}
                                          </Text>
                                        </Badge>
                                  )
                                  // If selected team is None or selected team's models are empty, show all models
                                : <Badge
                                    size={"xs"}
                                    className="mb-1"
                                    color="blue"
                                  >
                                    <Text>all-proxy-models</Text>
                                  </Badge>

                              }
                            </>
                          : item.models.map((model: string, index: number) =>
                              model === "all-proxy-models" ?
                                <Badge
                                  key={index}
                                  size={"xs"}
                                  className="mb-1"
                                  color="red"
                                >
                                  <Text>All Proxy Models</Text>
                                </Badge>
                              : model === "all-team-models" ?
                                <Badge
                                  key={index}
                                  size={"xs"}
                                  className="mb-1"
                                  color="red"
                                >
                                  <Text>All Team Models</Text>
                                </Badge>
                              : <Badge
                                  key={index}
                                  size={"xs"}
                                  className="mb-1"
                                  color="blue"
                                >
                                  <Text>
                                    {model.length > 30 ?
                                      `${getModelDisplayName(model).slice(0, 30)}...`
                                    : getModelDisplayName(model)}
                                  </Text>
                                </Badge>
                            )
                          }
                        </div>
                      : null}
                    </TableCell>

                    <TableCell>
                      <Text>
                        TPM: {item.tpm_limit ? item.tpm_limit : "Unlimited"}{" "}
                        <br></br> RPM:{" "}
                        {item.rpm_limit ? item.rpm_limit : "Unlimited"}
                      </Text>
                    </TableCell>
                    <TableCell>
                      <Button
                        size="xs"
                        onClick={() => handleModelLimitClick(item)}
                      >
                        Edit Limits
                      </Button>
                    </TableCell>
                    <TableCell>
                      <Icon
                        onClick={() => {
                          setSelectedToken(item);
                          setInfoDialogVisible(true);
                        }}
                        icon={InformationCircleIcon}
                        size="sm"
                      />

                      <Modal
                        open={infoDialogVisible}
                        onCancel={() => {
                          setInfoDialogVisible(false);
                          setSelectedToken(null);
                        }}
                        footer={null}
                        width={800}
                      >
                        {selectedToken && (
                          <>
                            <div className="grid grid-cols-1 gap-6 sm:grid-cols-2 lg:grid-cols-3 mt-8">
                              <Card>
                                <p className="text-tremor-default font-medium text-tremor-content dark:text-dark-tremor-content">
                                  Spend
                                </p>
                                <div className="mt-2 flex items-baseline space-x-2.5">
                                  <p className="text-tremor font-semibold text-tremor-content-strong dark:text-dark-tremor-content-strong">
                                    {(() => {
                                      try {
                                        return parseFloat(
                                          selectedToken.spend
                                        ).toFixed(4);
                                      } catch (error) {
                                        return selectedToken.spend;
                                      }
                                    })()}
                                  </p>
                                </div>
                              </Card>
                              <Card key={item.name}>
                                <p className="text-tremor-default font-medium text-tremor-content dark:text-dark-tremor-content">
                                  Budget
                                </p>
                                <div className="mt-2 flex items-baseline space-x-2.5">
                                  <p className="text-tremor font-semibold text-tremor-content-strong dark:text-dark-tremor-content-strong">
                                    {selectedToken.max_budget != null ?
                                      <>
                                        {selectedToken.max_budget}
                                        {selectedToken.budget_duration && (
                                          <>
                                            <br />
                                            Budget will be reset at{" "}
                                            {selectedToken.budget_reset_at ?
                                              new Date(
                                                selectedToken.budget_reset_at
                                              ).toLocaleString()
                                            : "Never"}
                                          </>
                                        )}
                                      </>
                                    : <>Unlimited</>}
                                  </p>
                                </div>
                              </Card>
                              <Card key={item.name}>
                                <p className="text-tremor-default font-medium text-tremor-content dark:text-dark-tremor-content">
                                  Expires
                                </p>
                                <div className="mt-2 flex items-baseline space-x-2.5">
                                  <p className="text-tremor-default font-small text-tremor-content-strong dark:text-dark-tremor-content-strong">
                                    {selectedToken.expires != null ?
                                      <>
                                        {new Date(
                                          selectedToken.expires
                                        ).toLocaleString(undefined, {
                                          day: "numeric",
                                          month: "long",
                                          year: "numeric",
                                          hour: "numeric",
                                          minute: "numeric",
                                          second: "numeric",
                                        })}
                                      </>
                                    : <>Never</>}
                                  </p>
                                </div>
                              </Card>
                            </div>

                            <Card className="my-4">
                              <Title>Token Name</Title>
                              <Text className="my-1">
                                {selectedToken.key_alias ?
                                  selectedToken.key_alias
                                : selectedToken.key_name}
                              </Text>
                              <Title>Token ID</Title>
                              <Text className="my-1 text-[12px]">
                                {selectedToken.token}
                              </Text>
                              <Title>User ID</Title>
                              <Text className="my-1 text-[12px]">
                                {selectedToken.user_id}
                              </Text>
                              <Title>Metadata</Title>
                              <Text className="my-1">
                                <pre>
                                  {JSON.stringify(selectedToken.metadata)}{" "}
                                </pre>
                              </Text>
                            </Card>

                            <Button
                              className="mx-auto flex items-center"
                              onClick={() => {
                                setInfoDialogVisible(false);
                                setSelectedToken(null);
                              }}
                            >
                              Close
                            </Button>
                          </>
                        )}
                      </Modal>
                      <Icon
                        icon={PencilAltIcon}
                        size="sm"
                        onClick={() => handleEditClick(item)}
                      />
                      <Icon
                        onClick={() => handleRegenerateClick(item)}
                        icon={RefreshIcon}
                        size="sm"
                      />
                      <Icon
                        onClick={() => handleDelete(item)}
                        icon={TrashIcon}
                        size="sm"
                      />
                    </TableCell>
                  </TableRow>
                );
              })}
          </TableBody>
        </Table>
        {isDeleteModalOpen && (
          <div className="fixed z-10 inset-0 overflow-y-auto">
            <div className="flex items-end justify-center min-h-screen pt-4 px-4 pb-20 text-center sm:block sm:p-0">
              <div
                className="fixed inset-0 transition-opacity"
                aria-hidden="true"
              >
                <div className="absolute inset-0 bg-gray-500 opacity-75"></div>
              </div>

              {/* Modal Panel */}
              <span
                className="hidden sm:inline-block sm:align-middle sm:h-screen"
                aria-hidden="true"
              >
                &#8203;
              </span>

              {/* Confirmation Modal Content */}
              <div className="inline-block align-bottom bg-white rounded-lg text-left overflow-hidden shadow-xl transform transition-all sm:my-8 sm:align-middle sm:max-w-lg sm:w-full">
                <div className="bg-white px-4 pt-5 pb-4 sm:p-6 sm:pb-4">
                  <div className="sm:flex sm:items-start">
                    <div className="mt-3 text-center sm:mt-0 sm:ml-4 sm:text-left">
                      <h3 className="text-lg leading-6 font-medium text-gray-900">
                        Delete Key
                      </h3>
                      <div className="mt-2">
                        <p className="text-sm text-gray-500">
                          Are you sure you want to delete this key ?
                        </p>
                      </div>
                    </div>
                  </div>
                </div>
                <div className="bg-gray-50 px-4 py-3 sm:px-6 sm:flex sm:flex-row-reverse">
                  <Button onClick={confirmDelete} color="red" className="ml-2">
                    Delete
                  </Button>
                  <Button onClick={cancelDelete}>Cancel</Button>
                </div>
              </div>
            </div>
          </div>
        )}
      </Card>

      {selectedToken && (
        <EditKeyModal
          visible={editModalVisible}
          onCancel={handleEditCancel}
          token={selectedToken}
          onSubmit={handleEditSubmit}
        />
      )}

      {selectedToken && (
        <ModelLimitModal
          visible={modelLimitModalVisible}
          onCancel={() => setModelLimitModalVisible(false)}
          token={selectedToken}
          onSubmit={handleModelLimitSubmit}
          accessToken={accessToken}
        />
      )}

      {/* Regenerate Key Form Modal */}
      <Modal
        title="Regenerate API Key"
        visible={regenerateDialogVisible}
        onCancel={() => {
          setRegenerateDialogVisible(false);
          regenerateForm.resetFields();
        }}
        footer={[
          <Button
            key="cancel"
            onClick={() => {
              setRegenerateDialogVisible(false);
              regenerateForm.resetFields();
            }}
            className="mr-2"
          >
            Cancel
          </Button>,
          <Button
            key="regenerate"
            onClick={handleRegenerateKey}
            disabled={!premiumUser}
          >
            {premiumUser ? "Regenerate" : "Upgrade to Regenerate"}
          </Button>,
        ]}
      >
        {premiumUser ?
          <Form
            form={regenerateForm}
            layout="vertical"
            onValuesChange={(changedValues, allValues) => {
              if ("duration" in changedValues) {
                handleRegenerateFormChange("duration", changedValues.duration);
              }
            }}
          >
            <Form.Item name="key_alias" label="Key Alias">
              <TextInput disabled={true} />
            </Form.Item>
            <Form.Item name="max_budget" label="Max Budget (USD)">
              <InputNumber
                step={0.01}
                precision={2}
                style={{ width: "100%" }}
              />
            </Form.Item>
            <Form.Item name="tpm_limit" label="TPM Limit">
              <InputNumber style={{ width: "100%" }} />
            </Form.Item>
            <Form.Item name="rpm_limit" label="RPM Limit">
              <InputNumber style={{ width: "100%" }} />
            </Form.Item>
            <Form.Item
              name="duration"
              label="Expire Key (eg: 30s, 30h, 30d)"
              className="mt-8"
            >
              <TextInput placeholder="" />
            </Form.Item>
            <div className="mt-2 text-sm text-gray-500">
              Current expiry:{" "}
              {selectedToken?.expires != null ?
                new Date(selectedToken.expires).toLocaleString()
              : "Never"}
            </div>
            {newExpiryTime && (
              <div className="mt-2 text-sm text-green-600">
                New expiry: {newExpiryTime}
              </div>
            )}
          </Form>
        : <div>
            <p className="mb-2 text-gray-500 italic text-[12px]">
              Upgrade to use this feature
            </p>
            <Button variant="primary" className="mb-2">
              <a
                href="https://calendly.com/d/4mp-gd3-k5k/litellm-1-1-onboarding-chat"
                target="_blank"
              >
                Get Free Trial
              </a>
            </Button>
          </div>
        }
      </Modal>

      {/* Regenerated Key Display Modal */}
      {regeneratedKey && (
        <Modal
          visible={!!regeneratedKey}
          onCancel={() => setRegeneratedKey(null)}
          footer={[
            <Button key="close" onClick={() => setRegeneratedKey(null)}>
              Close
            </Button>,
          ]}
        >
          <Grid numItems={1} className="gap-2 w-full">
            <Title>Regenerated Key</Title>
            <Col numColSpan={1}>
              <p>
                Please replace your old key with the new key generated. For
                security reasons, <b>you will not be able to view it again</b>{" "}
                through your LiteLLM account. If you lose this secret key, you
                will need to generate a new one.
              </p>
            </Col>
            <Col numColSpan={1}>
              <Text className="mt-3">Key Alias:</Text>
              <div
                style={{
                  background: "#f8f8f8",
                  padding: "10px",
                  borderRadius: "5px",
                  marginBottom: "10px",
                }}
              >
                <pre style={{ wordWrap: "break-word", whiteSpace: "normal" }}>
                  {selectedToken?.key_alias || "No alias set"}
                </pre>
              </div>
              <Text className="mt-3">New API Key:</Text>
              <div
                style={{
                  background: "#f8f8f8",
                  padding: "10px",
                  borderRadius: "5px",
                  marginBottom: "10px",
                }}
              >
                <pre style={{ wordWrap: "break-word", whiteSpace: "normal" }}>
                  {regeneratedKey}
                </pre>
              </div>
              <CopyToClipboard
                text={regeneratedKey}
                onCopy={() => message.success("API Key copied to clipboard")}
              >
                <Button className="mt-3">Copy API Key</Button>
              </CopyToClipboard>
            </Col>
          </Grid>
        </Modal>
      )}
    </div>
  );
};

export default ViewKeyTable;