import { html, nothing } from "lit";
import type {
  AgentIdentityResult,
  AgentsFilesListResult,
  AgentsListResult,
  ChannelsStatusSnapshot,
  CronJob,
  CronStatus,
  SkillStatusReport,
  ToolsCatalogResult,
} from "../types.ts";
import { renderAgentOverview } from "./agents-panels-overview.ts";
import {
  renderAgentFiles,
  renderAgentChannels,
  renderAgentCron,
} from "./agents-panels-status-files.ts";
import { renderAgentTools, renderAgentSkills } from "./agents-panels-tools-skills.ts";
import { renderAgentPipedream, type AgentPipedreamState } from "./agents-panel-pipedream.ts";
import { renderAgentZapier, type AgentZapierState } from "./agents-panel-zapier.ts";
import { renderAgentSubagents } from "./agents-panel-subagents.ts";
import { agentBadgeText, buildAgentContext, normalizeAgentLabel } from "./agents-utils.ts";

export type AgentsPanel = "overview" | "files" | "tools" | "skills" | "channels" | "subagents" | "cron";

export type ConfigState = {
  form: Record<string, unknown> | null;
  loading: boolean;
  saving: boolean;
  dirty: boolean;
};

export type ChannelsState = {
  snapshot: ChannelsStatusSnapshot | null;
  loading: boolean;
  error: string | null;
  lastSuccess: number | null;
};

export type CronState = {
  status: CronStatus | null;
  jobs: CronJob[];
  loading: boolean;
  error: string | null;
};

export type AgentFilesState = {
  list: AgentsFilesListResult | null;
  loading: boolean;
  error: string | null;
  active: string | null;
  contents: Record<string, string>;
  drafts: Record<string, string>;
  saving: boolean;
};

export type AgentSkillsState = {
  report: SkillStatusReport | null;
  loading: boolean;
  error: string | null;
  agentId: string | null;
  filter: string;
};

export type ToolsCatalogState = {
  loading: boolean;
  error: string | null;
  result: ToolsCatalogResult | null;
};

export type AgentsProps = {
  basePath: string;
  loading: boolean;
  error: string | null;
  agentsList: AgentsListResult | null;
  selectedAgentId: string | null;
  activePanel: AgentsPanel;
  config: ConfigState;
  channels: ChannelsState;
  cron: CronState;
  agentFiles: AgentFilesState;
  agentIdentityLoading: boolean;
  agentIdentityError: string | null;
  agentIdentityById: Record<string, AgentIdentityResult>;
  agentSkills: AgentSkillsState;
  toolsCatalog: ToolsCatalogState;
  onRefresh: () => void;
  onSelectAgent: (agentId: string) => void;
  onSelectPanel: (panel: AgentsPanel) => void;
  onLoadFiles: (agentId: string) => void;
  onSelectFile: (name: string) => void;
  onFileDraftChange: (name: string, content: string) => void;
  onFileReset: (name: string) => void;
  onFileSave: (name: string) => void;
  onToolsProfileChange: (agentId: string, profile: string | null, clearAllow: boolean) => void;
  onToolsOverridesChange: (agentId: string, alsoAllow: string[], deny: string[]) => void;
  agentToolsSubTab: "core" | "pipedream" | "zapier";
  onAgentToolsSubTabChange: (tab: "core" | "pipedream" | "zapier") => void;
  agentPipedreamState: AgentPipedreamState;
  onPipedreamSave: (externalUserId: string) => void;
  onPipedreamDelete: () => void;
  onPipedreamEditUserId: (editing: boolean) => void;
  onPipedreamDraftChange: (value: string) => void;
  onPipedreamRefresh: () => void;
  onPipedreamConnectApp: (slug: string) => void;
  onPipedreamDisconnectApp: (slug: string) => void;
  onPipedreamActivateApp: (slug: string) => void;
  onPipedreamTestApp: (slug: string) => void;
  onPipedreamToggleExpand: (slug: string) => void;
  onPipedreamPreviewTools: (app: { slug: string; name: string }) => void;
  onPipedreamCloseToolPreview: () => void;
  onPipedreamOpenAppBrowser: () => void;
  onPipedreamRefreshCatalog: () => void;
  onPipedreamCloseAppBrowser: () => void;
  onPipedreamAppBrowserSearchChange: (value: string) => void;
  onPipedreamManualSlugChange: (value: string) => void;
  onPipedreamConnectManualSlug: () => void;
  agentZapierState: AgentZapierState;
  onZapierSaveUrl: (url: string) => void;
  onZapierDelete: () => void;
  onZapierEditUrl: (editing: boolean) => void;
  onZapierDraftChange: (value: string) => void;
  onZapierRefresh: () => void;
  onZapierRefreshTools: () => void;
  onZapierToggleTool: (toolName: string, enabled: boolean) => void;
  onConfigReload: () => void;
  onConfigSave: () => void;
  onModelChange: (agentId: string, modelId: string | null) => void;
  onModelFallbacksChange: (agentId: string, fallbacks: string[]) => void;
  onAgentSubagentModelChange: (agentId: string, modelId: string | null) => void;
  onAgentSubagentFallbacksChange: (agentId: string, fallbacks: string[]) => void;
  onAgentSubagentThinkingChange: (agentId: string, value: string | null) => void;
  onDefaultSubagentModelChange: (modelId: string | null) => void;
  onDefaultSubagentFallbacksChange: (fallbacks: string[]) => void;
  onDefaultSubagentThinkingChange: (value: string | null) => void;
  onDefaultSubagentLimitChange: (
    key: "maxConcurrent" | "maxSpawnDepth" | "maxChildrenPerAgent",
    value: number | null,
  ) => void;
  avatarTheme: string;
  avatarInstructions: string;
  avatarBusy: boolean;
  avatarStatus: string | null;
  avatarError: string | null;
  avatarPreviewUrl: string | null;
  onAvatarUpload: (file: File) => void;
  onAvatarRemove: () => void;
  onAvatarThemeChange: (value: string) => void;
  onAvatarInstructionsChange: (value: string) => void;
  onAvatarGenerate: () => void;
  onAvatarKeep: () => void;
  onAvatarCancelPreview: () => void;
  onChannelsRefresh: () => void;
  onCronRefresh: () => void;
  onCronRunNow: (jobId: string) => void;
  onSkillsFilterChange: (next: string) => void;
  onSkillsRefresh: () => void;
  onAgentSkillToggle: (agentId: string, skillName: string, enabled: boolean) => void;
  onAgentSkillsClear: (agentId: string) => void;
  onAgentSkillsDisableAll: (agentId: string) => void;
  onSetDefault: (agentId: string) => void;
  availableModels?: Array<{ id: string; name?: string; provider: string; contextWindow?: number }>;
};

export function renderAgents(props: AgentsProps) {
  const agents = props.agentsList?.agents ?? [];
  const defaultId = props.agentsList?.defaultId ?? null;
  const selectedId = props.selectedAgentId ?? defaultId ?? agents[0]?.id ?? null;
  const selectedAgent = selectedId
    ? (agents.find((agent) => agent.id === selectedId) ?? null)
    : null;
  const selectedSkillCount =
    selectedId && props.agentSkills.agentId === selectedId
      ? (props.agentSkills.report?.skills?.length ?? null)
      : null;

  const channelEntryCount = props.channels.snapshot
    ? Object.keys(props.channels.snapshot.channelAccounts ?? {}).length
    : null;
  const cronJobCount = selectedId
    ? props.cron.jobs.filter((j) => j.agentId === selectedId).length
    : null;
  const tabCounts: Record<string, number | null> = {
    files: props.agentFiles.list?.files?.length ?? null,
    skills: selectedSkillCount,
    channels: channelEntryCount,
    cron: cronJobCount || null,
  };

  return html`
    <div class="agents-layout">
      <section class="agents-toolbar">
        <div class="agents-toolbar-row">
          <span class="agents-toolbar-label">Agent</span>
          <div class="agents-control-row">
            <div class="agents-control-select">
              <select
                class="agents-select"
                .value=${selectedId ?? ""}
                ?disabled=${props.loading || agents.length === 0}
                @change=${(e: Event) => props.onSelectAgent((e.target as HTMLSelectElement).value)}
              >
                ${
                  agents.length === 0
                    ? html`
                        <option value="">No agents</option>
                      `
                    : agents.map(
                        (agent) => html`
                        <option value=${agent.id} ?selected=${agent.id === selectedId}>
                          ${normalizeAgentLabel(agent)}${agentBadgeText(agent.id, defaultId) ? ` (${agentBadgeText(agent.id, defaultId)})` : ""}
                        </option>
                      `,
                      )
                }
              </select>
            </div>
            <div class="agents-control-actions">
              ${
                selectedAgent
                  ? html`
                      <div class="agent-actions-wrap">
                        <button
                          class="agent-actions-toggle"
                          type="button"
                          @click=${() => {
                            actionsMenuOpen = !actionsMenuOpen;
                          }}
                        >⋯</button>
                        ${
                          actionsMenuOpen
                            ? html`
                                <div class="agent-actions-menu">
                                  <button type="button" @click=${() => {
                                    void navigator.clipboard.writeText(selectedAgent.id);
                                    actionsMenuOpen = false;
                                  }}>Copy agent ID</button>
                                  <button
                                    type="button"
                                    ?disabled=${Boolean(defaultId && selectedAgent.id === defaultId)}
                                    @click=${() => {
                                      props.onSetDefault(selectedAgent.id);
                                      actionsMenuOpen = false;
                                    }}
                                  >
                                    ${defaultId && selectedAgent.id === defaultId ? "Already default" : "Set as default"}
                                  </button>
                                </div>
                              `
                            : nothing
                        }
                      </div>
                    `
                  : nothing
              }
              <button class="btn btn--sm agents-refresh-btn" ?disabled=${props.loading} @click=${props.onRefresh}>
                ${props.loading ? "Loading…" : "Refresh"}
              </button>
            </div>
          </div>
