'use client';

import { useEffect, useRef, useState, useMemo } from 'react';
import { Plus } from 'lucide-react';
import useSWR from 'swr';
import { getVisibleAgents, getOpenAgentConfig, listBackends, listBackendAgents, getBackendConfig, getClaudeCodeConfig, type Backend, type BackendAgent } from '@/lib/api';
import type { Provider, Workspace } from '@/lib/api';

interface NewMissionDialogProps {
  workspaces: Workspace[];
  providers?: Provider[];
  disabled?: boolean;
  onCreate: (options?: {
    workspaceId?: string;
    agent?: string;
    modelOverride?: string;
    backend?: string;
  }) => Promise<void> | void;
}

// Combined agent with backend info
interface CombinedAgent {
  backend: string;
  backendName: string;
  agent: string;
  value: string; // "backend:agent" format
}

// Parse agent names from API response
const parseAgentNames = (payload: unknown): string[] => {
  const normalizeEntry = (entry: unknown): string | null => {
    if (typeof entry === 'string') return entry;
    if (entry && typeof entry === 'object') {
      const name = (entry as { name?: unknown }).name;
      if (typeof name === 'string') return name;
      const id = (entry as { id?: unknown }).id;
      if (typeof id === 'string') return id;
    }
    return null;
  };

  const raw = Array.isArray(payload)
    ? payload
    : (payload as { agents?: unknown })?.agents;
  if (!Array.isArray(raw)) return [];

  const names = raw
    .map(normalizeEntry)
    .filter((name): name is string => Boolean(name));
  return Array.from(new Set(names));
};

export function NewMissionDialog({
  workspaces,
  providers = [],
  disabled = false,
  onCreate,
}: NewMissionDialogProps) {
  const [open, setOpen] = useState(false);
  const [newMissionWorkspace, setNewMissionWorkspace] = useState('');
  // Combined value: "backend:agent" or empty for default
  const [selectedAgentValue, setSelectedAgentValue] = useState('');
  const [newMissionModelOverride, setNewMissionModelOverride] = useState('');
  const [submitting, setSubmitting] = useState(false);
  const [defaultSet, setDefaultSet] = useState(false);
  const dialogRef = useRef<HTMLDivElement>(null);

  // SWR: fetch backends
  const { data: backends } = useSWR<Backend[]>('backends', listBackends, {
    revalidateOnFocus: false,
    dedupingInterval: 30000,
    fallbackData: [{ id: 'opencode', name: 'OpenCode' }, { id: 'claudecode', name: 'Claude Code' }],
  });

  // SWR: fetch backend configs to check enabled status
  const { data: opencodeConfig } = useSWR('backend-opencode-config', () => getBackendConfig('opencode'), {
    revalidateOnFocus: false,
    dedupingInterval: 30000,
  });
  const { data: claudecodeConfig } = useSWR('backend-claudecode-config', () => getBackendConfig('claudecode'), {
    revalidateOnFocus: false,
    dedupingInterval: 30000,
  });

  // Filter to only enabled backends
  const enabledBackends = useMemo(() => {
    return backends?.filter((b) => {
      if (b.id === 'opencode') return opencodeConfig?.enabled !== false;
      if (b.id === 'claudecode') return claudecodeConfig?.enabled !== false;
      return true;
    }) || [];
  }, [backends, opencodeConfig, claudecodeConfig]);

  // SWR: fetch agents for each enabled backend
  const { data: opencodeAgents } = useSWR<BackendAgent[]>(
    enabledBackends.some(b => b.id === 'opencode') ? 'backend-opencode-agents' : null,
    () => listBackendAgents('opencode'),
    { revalidateOnFocus: false, dedupingInterval: 30000 }
  );
  const { data: claudecodeAgents } = useSWR<BackendAgent[]>(
    enabledBackends.some(b => b.id === 'claudecode') ? 'backend-claudecode-agents' : null,
    () => listBackendAgents('claudecode'),
    { revalidateOnFocus: false, dedupingInterval: 30000 }
  );

  // SWR: fallback for opencode agents
  const { data: agentsPayload } = useSWR('opencode-agents', getVisibleAgents, {
    revalidateOnFocus: false,
    dedupingInterval: 30000,
  });
  const { data: config } = useSWR('openagent-config', getOpenAgentConfig, {
    revalidateOnFocus: false,
    dedupingInterval: 30000,
  });

  // SWR: fetch Claude Code config for hidden agents
  const { data: claudeCodeLibConfig } = useSWR(
    enabledBackends.some(b => b.id === 'claudecode') ? 'claudecode-lib-config' : null,
    getClaudeCodeConfig,
    { revalidateOnFocus: false, dedupingInterval: 30000 }
  );

  // Combine all agents from enabled backends
  const allAgents = useMemo((): CombinedAgent[] => {
    const result: CombinedAgent[] = [];
    const claudeCodeHiddenAgents = claudeCodeLibConfig?.hidden_agents || [];

    for (const backend of enabledBackends) {
      let agentNames: string[] = [];

      if (backend.id === 'opencode') {
        agentNames = opencodeAgents?.map(a => a.name) || parseAgentNames(agentsPayload);
      } else if (backend.id === 'claudecode') {
        // Filter out hidden Claude Code agents
        const allClaudeAgents = claudecodeAgents?.map(a => a.name) || [];
        agentNames = allClaudeAgents.filter(name => !claudeCodeHiddenAgents.includes(name));
      }

      for (const agent of agentNames) {
        result.push({
          backend: backend.id,
          backendName: backend.name,
          agent,
          value: `${backend.id}:${agent}`,
        });
      }
    }

    return result;
  }, [enabledBackends, opencodeAgents, claudecodeAgents, agentsPayload, claudeCodeLibConfig]);

  // Group agents by backend for display
  const agentsByBackend = useMemo(() => {
    const groups: Record<string, CombinedAgent[]> = {};
    for (const agent of allAgents) {
      if (!groups[agent.backend]) {
        groups[agent.backend] = [];
      }
      groups[agent.backend].push(agent);
    }
    return groups;
  }, [allAgents]);

  // Parse selected value to get backend and agent
  const parseSelectedValue = (value: string): { backend: string; agent: string } | null => {
    if (!value) return null;
    const [backend, ...agentParts] = value.split(':');
    const agent = agentParts.join(':'); // Handle agent names with colons
    return backend && agent ? { backend, agent } : null;
  };

  // Get the currently selected backend
  const selectedBackend = useMemo(() => {
    const parsed = parseSelectedValue(selectedAgentValue);
    return parsed?.backend || null;
  }, [selectedAgentValue]);

  // Filter providers based on selected backend
  // Claude Code only supports Anthropic models
  const filteredProviders = useMemo(() => {
    if (selectedBackend === 'claudecode') {
      // Only show Anthropic (Claude) models for Claude Code
      return providers.filter(p => p.id === 'anthropic');
    }
    // Show all providers for OpenCode or when no backend is selected
    return providers;
  }, [providers, selectedBackend]);

  const formatWorkspaceType = (type: Workspace['workspace_type']) =>
    type === 'host' ? 'host' : 'isolated';

  // Reset model override when switching to Claude Code if current model isn't Anthropic
  useEffect(() => {
    if (selectedBackend === 'claudecode' && newMissionModelOverride) {
      // Check if current model is from Anthropic
      if (!newMissionModelOverride.startsWith('anthropic/')) {
        setNewMissionModelOverride('');
      }
    }
  }, [selectedBackend, newMissionModelOverride]);

  // Click outside handler
  useEffect(() => {
    if (!open) return;

    const handleClickOutside = (event: MouseEvent) => {
      if (dialogRef.current && !dialogRef.current.contains(event.target as Node)) {
        setOpen(false);
      }
    };

    document.addEventListener('mousedown', handleClickOutside);
    return () => document.removeEventListener('mousedown', handleClickOutside);
  }, [open]);

  // Set default agent when dialog opens (only once per open)
  useEffect(() => {
    if (!open || defaultSet) return;
    // Wait for config to finish loading
    if (config === undefined) return;
    // Wait for agents to load
    if (allAgents.length === 0) return;

    // Try to find the default agent from config
    if (config?.default_agent) {
      const defaultAgent = allAgents.find(a => a.agent === config.default_agent);
      if (defaultAgent) {
        setSelectedAgentValue(defaultAgent.value);
        setDefaultSet(true);
        return;
      }
    }

    // Fallback: try Sisyphus in OpenCode
    const sisyphus = allAgents.find(a => a.backend === 'opencode' && a.agent === 'Sisyphus');
    if (sisyphus) {
      setSelectedAgentValue(sisyphus.value);
      setDefaultSet(true);
      return;
    }

    // Fallback: use first available agent
    if (allAgents.length > 0) {
      setSelectedAgentValue(allAgents[0].value);
    }
    setDefaultSet(true);
  }, [open, defaultSet, allAgents, config]);

  const resetForm = () => {
    setNewMissionWorkspace('');
    setSelectedAgentValue('');
    setNewMissionModelOverride('');
    setDefaultSet(false);
  };

  const handleCancel = () => {
    setOpen(false);
    resetForm();
  };

  const handleCreate = async () => {
    if (disabled || submitting) return;
    setSubmitting(true);
    try {
      const parsed = parseSelectedValue(selectedAgentValue);
      await onCreate({
        workspaceId: newMissionWorkspace || undefined,
        agent: parsed?.agent || undefined,
        modelOverride: newMissionModelOverride || undefined,
        backend: parsed?.backend || 'opencode',
      });
      setOpen(false);
      resetForm();
    } finally {
      setSubmitting(false);
    }
  };

  const isBusy = disabled || submitting;

  // Determine default label based on enabled backends
  const defaultBackendName = enabledBackends[0]?.name || 'OpenCode';

  return (
    <div className="relative" ref={dialogRef}>
      <button
        type="button"
        onClick={() => setOpen((prev) => !prev)}
        disabled={isBusy}
        className="flex items-center gap-2 rounded-lg bg-indigo-500/20 px-3 py-2 text-sm font-medium text-indigo-400 hover:bg-indigo-500/30 transition-colors disabled:opacity-50"
      >
        <Plus className="h-4 w-4" />
        <span className="hidden sm:inline">New</span> Mission
      </button>
      {open && (
        <div className="absolute right-0 top-full mt-1 w-96 rounded-lg border border-white/[0.06] bg-[#1a1a1a] p-4 shadow-xl z-50">
          <h3 className="text-sm font-medium text-white mb-3">Create New Mission</h3>
          <div className="space-y-3">
            {/* Workspace selection */}
            <div>
              <label className="block text-xs text-white/50 mb-1.5">Workspace</label>
              <select
                value={newMissionWorkspace}
                onChange={(e) => setNewMissionWorkspace(e.target.value)}
                className="w-full rounded-lg border border-white/[0.06] bg-white/[0.02] px-3 py-2.5 text-sm text-white focus:border-indigo-500/50 focus:outline-none appearance-none cursor-pointer"
                style={{
                  backgroundImage:
                    "url(\"data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 20 20'%3e%3cpath stroke='%236b7280' stroke-linecap='round' stroke-linejoin='round' stroke-width='1.5' d='M6 8l4 4 4-4'/%3e%3c/svg%3e\")",
                  backgroundPosition: 'right 0.5rem center',
                  backgroundRepeat: 'no-repeat',
                  backgroundSize: '1.5em 1.5em',
                  paddingRight: '2.5rem',
                }}
              >
                <option value="" className="bg-[#1a1a1a]">
                  Host (default)
                </option>
                {workspaces
                  .filter(
                    (ws) =>
                      ws.status === 'ready' &&
                      ws.id !== '00000000-0000-0000-0000-000000000000'
                  )
                  .map((workspace) => (
                    <option
                      key={workspace.id}
                      value={workspace.id}
                      className="bg-[#1a1a1a]"
                    >
                      {workspace.name} ({formatWorkspaceType(workspace.workspace_type)})
                    </option>
                  ))}
              </select>
              <p className="text-xs text-white/30 mt-1.5">Where the mission will run</p>
            </div>

            {/* Agent selection (includes backend) */}
            <div>
              <label className="block text-xs text-white/50 mb-1.5">Agent</label>
              <select
                value={selectedAgentValue}
                onChange={(e) => setSelectedAgentValue(e.target.value)}
                className="w-full rounded-lg border border-white/[0.06] bg-white/[0.02] px-3 py-2.5 text-sm text-white focus:border-indigo-500/50 focus:outline-none appearance-none cursor-pointer"
                style={{
                  backgroundImage:
                    "url(\"data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 20 20'%3e%3cpath stroke='%236b7280' stroke-linecap='round' stroke-linejoin='round' stroke-width='1.5' d='M6 8l4 4 4-4'/%3e%3c/svg%3e\")",
                  backgroundPosition: 'right 0.5rem center',
                  backgroundRepeat: 'no-repeat',
                  backgroundSize: '1.5em 1.5em',
                  paddingRight: '2.5rem',
                }}
              >
                {enabledBackends.map((backend) => {
                  const backendAgentsList = agentsByBackend[backend.id] || [];
                  if (backendAgentsList.length === 0) return null;

                  return (
                    <optgroup key={backend.id} label={backend.name} className="bg-[#1a1a1a]">
                      {backendAgentsList.map((agent) => (
                        <option key={agent.value} value={agent.value} className="bg-[#1a1a1a]">
                          {agent.agent}{agent.backend === 'opencode' && agent.agent === 'Sisyphus' ? ' (recommended)' : ''}
                        </option>
                      ))}
                    </optgroup>
                  );
                })}
              </select>
              <p className="text-xs text-white/30 mt-1.5">
                Select an agent and backend to power this mission
              </p>
            </div>

            {/* Model override */}
            <div>
              <label className="block text-xs text-white/50 mb-1.5">Model Override</label>
              <select
                value={newMissionModelOverride}
                onChange={(e) => setNewMissionModelOverride(e.target.value)}
                className="w-full rounded-lg border border-white/[0.06] bg-white/[0.02] px-3 py-2.5 text-sm text-white focus:border-indigo-500/50 focus:outline-none appearance-none cursor-pointer"
                style={{
                  backgroundImage:
                    "url(\"data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 20 20'%3e%3cpath stroke='%236b7280' stroke-linecap='round' stroke-linejoin='round' stroke-width='1.5' d='M6 8l4 4 4-4'/%3e%3c/svg%3e\")",
                  backgroundPosition: 'right 0.5rem center',
                  backgroundRepeat: 'no-repeat',
                  backgroundSize: '1.5em 1.5em',
                  paddingRight: '2.5rem',
                }}
              >
                <option value="" className="bg-[#1a1a1a]">
                  Default (agent or global)
                </option>
                {filteredProviders.map((provider) => (
                  <optgroup key={provider.id} label={provider.name} className="bg-[#1a1a1a]">
                    {provider.models.map((model) => (
                      <option
                        key={`${provider.id}/${model.id}`}
                        value={`${provider.id}/${model.id}`}
                        className="bg-[#1a1a1a]"
                      >
                        {model.name || model.id}
                      </option>
                    ))}
                  </optgroup>
                ))}
              </select>
              <p className="text-xs text-white/30 mt-1.5">
                Overrides the model for this mission
              </p>
            </div>

            <div className="flex gap-2 pt-1">
              <button
                type="button"
                onClick={handleCancel}
                className="flex-1 rounded-lg border border-white/[0.06] bg-white/[0.02] px-3 py-2 text-sm text-white/70 hover:bg-white/[0.04] transition-colors"
              >
                Cancel
              </button>
              <button
                type="button"
                onClick={handleCreate}
                disabled={isBusy}
                className="flex-1 rounded-lg bg-indigo-500 px-3 py-2 text-sm font-medium text-white hover:bg-indigo-600 transition-colors disabled:opacity-50"
              >
                Create
              </button>
            </div>
          </div>
        </div>
      )}
    </div>
  );
}
