import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import {
  Select,
  SelectContent,
  SelectItem,
  SelectTrigger,
  SelectValue,
} from "@/components/ui/select";
import {
  AgentProfile,
  AgentRef,
  DEFAULT_PROFILE_NAME,
  ToolGroup,
} from "@/store";
import sortBy from "lodash/sortBy";
import { CopyPlus, Info, Plus, Trash2 } from "lucide-react";
import { useState } from "react";
import { MultiSelect } from "./MultiSelect";
import { MultiSelectTools } from "./MultiSelectTools";
import { ToolGroupModal } from "./ToolGroupModal";

const AgentProfileRow = ({
  agentsOptions,
  isDefaultProfile = false,
  isPendingUpdateAppConfig,
  handleProfileChange,
  onCreateNewAgent,
  onCreateNewToolGroup,
  onDuplicateProfile,
  onRemoveProfile,
  profile,
  toolGroups,
}: {
  agentsOptions: {
    label: string;
    agentRef: AgentRef;
    value: string;
    disabled?: boolean;
  }[];
  isDefaultProfile?: boolean;
  isPendingUpdateAppConfig: boolean;
  handleProfileChange: (
    id: string,
    field: keyof AgentProfile,
    value: AgentProfile[keyof AgentProfile],
  ) => void;
  onCreateNewAgent: (newAgentName: string) => void;
  onCreateNewToolGroup: () => void;
  onDuplicateProfile: (profileId: string) => void;
  onRemoveProfile: (profileId: string) => void;
  profile: AgentProfile;
  toolGroups: ToolGroup[];
}) => {
  const [focused, setFocused] = useState(false);
  const handleFocus = () => setFocused(true);
  const handleBlur = () => setFocused(false);
  const shouldAutoFocus = focused && !isDefaultProfile;
  const enableRemoveButton = !isDefaultProfile;
  const enableDuplicateButton = !isDefaultProfile && profile.name !== "";

  if (!profile) {
    return null;
  }

  const handleAgentsChange = (agentName: string) => {
    const currentAgents = profile.agents || [];
    const isSelected = currentAgents.some((a) => a.name === agentName);
    if (isSelected) {
      handleProfileChange(
        profile.id,
        "agents",
        sortBy(
          currentAgents.filter((a) => a.name !== agentName),
          (a) => a.name.toLowerCase(),
        ),
      );
      return;
    }
    const agentRef = agentsOptions.find((o) => o.value === agentName)?.agentRef;
    if (!agentRef) return;
    handleProfileChange(
      profile.id,
      "agents",
      sortBy([...currentAgents, agentRef], (a) => a.name.toLowerCase()),
    );
  };

  const handleToolGroupsChange = (toolGroup: string) => {
    const currentToolGroups = profile.toolGroups || [];
    const newToolGroups = currentToolGroups.includes(toolGroup)
      ? currentToolGroups.filter((tg) => tg !== toolGroup)
      : [...currentToolGroups, toolGroup];
    handleProfileChange(
      profile.id,
      "toolGroups",
      sortBy(newToolGroups, (tg) => tg.toLowerCase()),
    );
  };

  return (
    <tr className="border-t border-border">
      <td className="p-2 w-64">
        <Input
          value={profile.name}
          onChange={(e) =>
            handleProfileChange(profile.id, "name", e.target.value)
          }
          placeholder="Profile Name"
          className="bg-background shadow-none rounded-md border font-normal"
          disabled={isDefaultProfile || isPendingUpdateAppConfig}
          autoFocus={shouldAutoFocus}
          onFocus={handleFocus}
          onBlur={handleBlur}
        />
      </td>
      <td className="p-2 w-64">
        <MultiSelect
          options={agentsOptions}
          selected={profile.agents.map((a) => a.name)}
          onCreateNew={onCreateNewAgent}
          onSelectionChange={handleAgentsChange}
          getTriggerText={(selected) =>
            isDefaultProfile
              ? "any agent"
              : selected.length > 0
                ? `${selected.length} selected`
                : `Select Agents...`
          }
          disabled={isDefaultProfile || isPendingUpdateAppConfig}
        />
      </td>
      <td className="p-2 w-64">
        <Select
          value={profile.permission}
          onValueChange={(value) =>
            handleProfileChange(profile.id, "permission", value)
          }
          disabled={isPendingUpdateAppConfig}
        >
          <SelectTrigger className="bg-background">
            <SelectValue />
          </SelectTrigger>
          <SelectContent>
            <SelectItem value="allow">Allow</SelectItem>
            <SelectItem value="allow-all">Allow All</SelectItem>
            <SelectItem value="block">Block</SelectItem>
            <SelectItem value="block-all">Block All</SelectItem>
          </SelectContent>
        </Select>
      </td>
      <td className="p-2 w-64">
        <MultiSelectTools
          title="Tool Groups"
          options={toolGroups}
          selected={profile.toolGroups}
          onSelectionChange={handleToolGroupsChange}
          onCreateNew={onCreateNewToolGroup}
          disabled={
            isPendingUpdateAppConfig ||
            profile.permission === "allow-all" ||
            profile.permission === "block-all"
          }
          placeholder={
            profile.permission === "allow-all" ||
            profile.permission === "block-all"
              ? "All Tools"
              : undefined
          }
        />
      </td>
      <td className="p-2 flex items-center justify-end gap-2">
        {enableDuplicateButton && (
          <Button
            onClick={() => onDuplicateProfile(profile.id)}
            size="icon"
            variant="secondary"
            className="text-primary hover:text-primary/80"
            disabled={isPendingUpdateAppConfig}
          >
            <CopyPlus className="w-4 h-4" />
          </Button>
        )}
        {enableRemoveButton && (
          <Button
            onClick={() => onRemoveProfile(profile.id)}
            size="icon"
            variant="secondary"
            className="text-primary"
            disabled={isPendingUpdateAppConfig}
          >
            <Trash2 className="w-4 h-4" />
          </Button>
        )}
      </td>
    </tr>
  );
};

export function AgentProfiles({
  agents = [],
  getIsAgentDisabledForProfile,
  isPendingUpdateAppConfig,
  mcpServers,
  profiles,
  setAgentsList,
  setProfiles,
  setToolGroups,
  toolGroups,
}: {
  agents: AgentRef[];
  getIsAgentDisabledForProfile: ({
    profileId,
    agentId,
  }: {
    profileId: string;
    agentId: string;
  }) => boolean;
  isPendingUpdateAppConfig: boolean;
  mcpServers: {
    name: string;
    tools: {
      name: string;
      description: string | undefined;
    }[];
  }[];
  profiles: AgentProfile[];
  setAgentsList: (updater: (agents: AgentRef[]) => AgentRef[]) => void;
  setProfiles: (updater: (profiles: AgentProfile[]) => AgentProfile[]) => void;
  setToolGroups: (updater: (toolGroups: ToolGroup[]) => ToolGroup[]) => void;
  toolGroups: ToolGroup[];
}) {
  const [showCreateToolGroup, setShowCreateToolGroup] = useState(false);
  const [newToolGroupProfileId, setNewToolGroupProfileId] = useState("");
  const [showInfoSection, setShowInfoSection] = useState(false);

  const handleProfileChange = (
    id: string,
    field: keyof AgentProfile,
    value: AgentProfile[keyof AgentProfile],
  ) => {
    setProfiles((prev) =>
      prev.map((p) => (p.id === id ? { ...p, [field]: value } : p)),
    );
  };

  const addProfile = () => {
    let profileNumber = 1;
    let profileName = `Profile ${profileNumber}`;

    // Unique profile name
    while (profiles.some((p) => p.name === profileName)) {
      profileNumber++;
      profileName = `Profile ${profileNumber}`;
    }

    const newProfile: AgentProfile = {
      id: `profile_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`,
      name: profileName,
      permission: "allow",
      agents: [],
      toolGroups: [],
    };

    setProfiles((prev) => [...prev, newProfile]);
  };

  const duplicateProfile = (profileId: string) => {
    const profile = profiles.find((p) => p.id === profileId);
    if (!profile) return;

    let copyNumber = 1;
    let copyName = `${profile.name} (Copy ${copyNumber})`;

    // Unique copy name
    while (profiles.some((p) => p.name === copyName)) {
      copyNumber++;
      copyName = `${profile.name} (Copy ${copyNumber})`;
    }

    const newProfile: AgentProfile = {
      ...profile,
      id: `profile_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`,
      name: copyName,
      agents: [],
    };

    setProfiles((prev) => [...prev, newProfile]);
  };

  const removeProfile = (profileId: string) => {
    setProfiles((prev) => prev.filter((p) => p.id !== profileId));
  };

  const saveNewToolGroup = (newGroup: ToolGroup) => {
    newGroup = {
      ...newGroup,
      id: `tool_group_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`,
    };
    setToolGroups((prev) => [...prev, newGroup]);
    handleProfileChange(newToolGroupProfileId, "toolGroups", [
      ...(profiles.find((p) => p.id === newToolGroupProfileId)?.toolGroups ||
        []),
      newGroup.id,
    ]);
    setNewToolGroupProfileId("");
    setShowCreateToolGroup(false);
  };

  const handleCreateNewAgent = (newAgentName: string) => {
    setAgentsList((prev) => {
      const exists = prev.some((a) => a.name === newAgentName);
      return exists
        ? prev
        : [...prev, { name: newAgentName, identityType: "consumers" as const }];
    });
  };

  const handleCreateNewToolGroup = (id: string) => {
    setNewToolGroupProfileId(id);
    setShowCreateToolGroup(true);
  };

  const allAgentsOptions = agents.map((agent) => ({
    agentRef: agent,
    label: agent.name,
    value: agent.name,
    disabled: false,
  }));

  return (
    <div className="space-y-6">
      <div className="flex justify-between items-center">
        <div className="flex items-center gap-2">
          <h3
            className="text-lg font-medium flex items-center cursor-pointer hover:text-primary"
            onClick={() => setShowInfoSection(!showInfoSection)}
          >
            Agent Profile Permissions
            <Info
              className="ml-2 w-4 h-4 text-primary hover:text-primary/80 cursor-pointer"
              onClick={(e) => {
                e.stopPropagation();
                setShowInfoSection(!showInfoSection);
              }}
            />
          </h3>
        </div>
        <Button
          onClick={addProfile}
          size="sm"
          variant="secondary"
          className="px-2 border-ring text-primary hover:bg-accent hover:text-primary/80 focus:text-primary/80 focus:bg-accent"
        >
          <Plus className="w-4 h-4 mr-2" />
          Add Profile
        </Button>
      </div>

      {showInfoSection && (
        <div className="text-sm text-muted-foreground bg-muted p-3 rounded-lg border border-border">
          <p>
            Each agent can be assigned to only one profile, unassigned agents
            will use the "Default" profile.
          </p>
          <p className="mt-2 text-xs">
            Available agents:{" "}
            {
              agents.filter(
                (agent) =>
                  !profiles.some(
                    (p) =>
                      p.name !== DEFAULT_PROFILE_NAME &&
                      p.agents.some((a) => a.name === agent.name),
                  ),
              ).length
            }{" "}
            of {agents.length}
          </p>
        </div>
      )}

      {showCreateToolGroup && (
        <ToolGroupModal
          mcpServers={mcpServers}
          onClose={() => setShowCreateToolGroup(false)}
          saveToolGroup={saveNewToolGroup}
          toolGroups={toolGroups}
        />
      )}

      <div className="border border-border rounded-lg overflow-x-auto">
        <table className="w-full text-sm">
          <thead className="bg-muted">
            <tr className="text-left font-medium">
              <th className="p-3">Profile</th>
              <th className="p-3">Agents</th>
              <th className="p-3">Permission Type</th>
              <th className="p-3">Tools</th>
              <th className="p-3 text-end">Actions</th>
            </tr>
          </thead>
          <tbody>
            {profiles.map((profile, index) => (
              <AgentProfileRow
                key={profile.id}
                agentsOptions={allAgentsOptions.map((agent) => ({
                  disabled: getIsAgentDisabledForProfile({
                    profileId: profile.id,
                    agentId: agent.value,
                  }),
                  label: agent.label,
                  value: agent.value,
                  agentRef: agent.agentRef,
                }))}
                handleProfileChange={handleProfileChange}
                isDefaultProfile={index === 0}
                isPendingUpdateAppConfig={isPendingUpdateAppConfig}
                onCreateNewAgent={handleCreateNewAgent}
                onCreateNewToolGroup={() =>
                  handleCreateNewToolGroup(profile.id)
                }
                onDuplicateProfile={duplicateProfile}
                onRemoveProfile={removeProfile}
                profile={profile}
                toolGroups={toolGroups}
              />
            ))}
          </tbody>
        </table>
      </div>
    </div>
  );
}
