import { useEffect, useState } from 'react';
import { Link } from 'react-router-dom';
import { useBotStore, type Bot } from '../stores/bot.ts';
import { useServerStore } from '../stores/server.ts';
import { useChannelStore } from '../stores/channel.ts';

// ponytail: config fields per bot type, add new types here
const BOT_TYPE_CONFIGS: Record<string, { label: string; fields: { key: string; label: string; type: 'text' | 'number' | 'channel'; placeholder: string }[] }> = {
  steamfree: {
    label: 'Steam Free Games',
    fields: [
      { key: 'channel_id', label: 'CHANNEL', type: 'channel', placeholder: 'select channel' },
      { key: 'poll_minutes', label: 'POLL INTERVAL (min)', type: 'number', placeholder: '30' },
    ],
  },
};

export function BotManager() {
  const bots = useBotStore((s) => s.bots);
  const loading = useBotStore((s) => s.loading);
  const error = useBotStore((s) => s.error);
  const fetchBots = useBotStore((s) => s.fetchBots);
  const createBot = useBotStore((s) => s.createBot);
  const updateBot = useBotStore((s) => s.updateBot);
  const deleteBot = useBotStore((s) => s.deleteBot);
  const addToServer = useBotStore((s) => s.addToServer);
  const regenerateToken = useBotStore((s) => s.regenerateToken);

  const servers = useServerStore((s) => s.servers);
  const fetchServers = useServerStore((s) => s.fetchServers);
  const channelsByServer = useChannelStore((s) => s.channelsByServer);
  const fetchChannels = useChannelStore((s) => s.fetchChannels);

  const [showCreate, setShowCreate] = useState(false);
  const [createName, setCreateName] = useState('');
  const [createDesc, setCreateDesc] = useState('');
  const [createType, setCreateType] = useState('');
  const [createConfig, setCreateConfig] = useState<Record<string, string>>({});
  const [channelServerId, setChannelServerId] = useState('');
  const [editingId, setEditingId] = useState<string | null>(null);
  const [editName, setEditName] = useState('');
  const [editDesc, setEditDesc] = useState('');
  const [tokenDisplay, setTokenDisplay] = useState<{ botId: string; token: string } | null>(null);
  const [addToServerBotId, setAddToServerBotId] = useState<string | null>(null);
  const [selectedServer, setSelectedServer] = useState('');
  const [copied, setCopied] = useState(false);

  useEffect(() => {
    fetchBots();
    fetchServers();
  }, [fetchBots, fetchServers]);

  const handleCreate = async (e: React.FormEvent) => {
    e.preventDefault();
    if (!createName.trim()) return;
    try {
      // Build config object with proper types
      const cfg: Record<string, unknown> = {};
      for (const [k, v] of Object.entries(createConfig)) {
        if (v === '') continue;
        const fieldDef = BOT_TYPE_CONFIGS[createType]?.fields.find((f) => f.key === k);
        cfg[k] = fieldDef?.type === 'number' ? parseInt(v, 10) : v;
      }
      const result = await createBot(createName.trim(), createDesc.trim(), createType || undefined, Object.keys(cfg).length ? cfg : undefined);
      setTokenDisplay({ botId: result.id, token: result.token });
      setCreateName('');
      setCreateDesc('');
      setCreateType('');
      setCreateConfig({});
      setChannelServerId('');
      setShowCreate(false);
    } catch {
      // error handled in store
    }
  };

  const handleUpdate = async (e: React.FormEvent) => {
    e.preventDefault();
    if (!editingId) return;
    try {
      await updateBot(editingId, { name: editName.trim(), description: editDesc.trim() });
      setEditingId(null);
    } catch {
      // error handled in store
    }
  };

  const handleDelete = async (id: string, name: string) => {
    if (!window.confirm(`Delete bot "${name}"? This cannot be undone.`)) return;
    try {
      await deleteBot(id);
    } catch {
      // error handled in store
    }
  };

  const handleRegenerate = async (id: string) => {
    if (!window.confirm('Regenerate token? The old token will be invalidated.')) return;
    try {
      const result = await regenerateToken(id);
      setTokenDisplay({ botId: id, token: result.token });
    } catch {
      // error handled in store
    }
  };

  const handleAddToServer = async () => {
    if (!addToServerBotId || !selectedServer) return;
    try {
      await addToServer(addToServerBotId, selectedServer);
      setAddToServerBotId(null);
      setSelectedServer('');
    } catch {
      // error handled in store
    }
  };

  const handleCopyToken = () => {
    if (tokenDisplay) {
      navigator.clipboard.writeText(tokenDisplay.token);
      setCopied(true);
      setTimeout(() => setCopied(false), 2000);
    }
  };

  const startEdit = (bot: Bot) => {
    setEditingId(bot.id);
    setEditName(bot.name);
    setEditDesc(bot.description);
  };

  const typeConfig = createType ? BOT_TYPE_CONFIGS[createType] : null;

  return (
    <div className="h-full w-full bg-gb-bg p-4 md:p-8 overflow-y-auto">
      <div className="max-w-3xl mx-auto">
        <div className="border border-gb-bg-t p-6">
          <pre className="text-gb-orange font-mono text-center mb-6">
            {'┌──────────────────────────────────┐\n'}
            {'│      === BOT MANAGER ===         │\n'}
            {'└──────────────────────────────────┘'}
          </pre>

          {error && (
            <p className="text-gb-red text-sm font-mono mb-4">ERR: {error}</p>
          )}

          {/* Token display overlay */}
          {tokenDisplay && (
            <div className="border border-gb-green bg-gb-bg-s p-4 mb-4">
              <p className="text-gb-green text-sm font-mono mb-2">
                {'>'} TOKEN GENERATED — copy it now, it won't be shown again:
              </p>
              <div className="flex items-center gap-2">
                <code className="text-gb-fg bg-gb-bg px-2 py-1 border border-gb-bg-t flex-1 text-xs break-all">
                  {tokenDisplay.token}
                </code>
                <button
                  type="button"
                  onClick={handleCopyToken}
                  className="terminal-button text-xs shrink-0"
                >
                  {copied ? '[COPIED]' : '[COPY]'}
                </button>
              </div>
              <button
                type="button"
                onClick={() => setTokenDisplay(null)}
                className="text-gb-fg-f hover:text-gb-aqua font-mono text-xs mt-2"
              >
                [DISMISS]
              </button>
            </div>
          )}

          {/* Create bot form */}
          <div className="mb-6">
            {!showCreate ? (
              <button
                type="button"
                onClick={() => setShowCreate(true)}
                className="terminal-button"
              >
                [CREATE BOT]
              </button>
            ) : (
              <form onSubmit={handleCreate} className="border border-gb-bg-t p-4 space-y-3">
                <p className="text-gb-aqua font-mono text-sm">{'>'} NEW BOT</p>
                <div>
                  <label className="block text-gb-fg-f mb-1 font-mono text-xs">NAME:</label>
                  <input
                    type="text"
                    value={createName}
                    onChange={(e) => setCreateName(e.target.value.slice(0, 32))}
                    maxLength={32}
                    className="terminal-input w-full"
                    placeholder="my-cool-bot"
                    autoFocus
                  />
                </div>
                <div>
                  <label className="block text-gb-fg-f mb-1 font-mono text-xs">DESCRIPTION:</label>
                  <input
                    type="text"
                    value={createDesc}
                    onChange={(e) => setCreateDesc(e.target.value.slice(0, 256))}
                    maxLength={256}
                    className="terminal-input w-full"
                    placeholder="what does this bot do?"
                  />
                </div>
                <div>
                  <label className="block text-gb-fg-f mb-1 font-mono text-xs">TYPE:</label>
                  <select
                    value={createType}
                    onChange={(e) => { setCreateType(e.target.value); setCreateConfig({}); }}
                    className="terminal-input w-full"
                  >
                    <option value="">External (connects via WebSocket)</option>
                    {Object.entries(BOT_TYPE_CONFIGS).map(([key, cfg]) => (
                      <option key={key} value={key}>{cfg.label}</option>
                    ))}
                  </select>
                </div>
                {typeConfig && typeConfig.fields.map((field) => (
                  <div key={field.key}>
                    <label className="block text-gb-fg-f mb-1 font-mono text-xs">{field.label}:</label>
                    {field.type === 'channel' ? (
                      <div className="space-y-1">
                        <select
                          value={channelServerId}
                          onChange={(e) => {
                            setChannelServerId(e.target.value);
                            setCreateConfig((prev) => ({ ...prev, [field.key]: '' }));
                            if (e.target.value) fetchChannels(e.target.value);
                          }}
                          className="terminal-input w-full"
                        >
                          <option value="">-- select server first --</option>
                          {servers.map((s) => (
                            <option key={s.id} value={s.id}>{s.name}</option>
                          ))}
                        </select>
                        <select
                          value={createConfig[field.key] || ''}
                          onChange={(e) => setCreateConfig((prev) => ({ ...prev, [field.key]: e.target.value }))}
                          className="terminal-input w-full"
                          disabled={!channelServerId}
                        >
                          <option value="">-- select channel --</option>
                          {(channelsByServer[channelServerId] || [])
                            .filter((c) => c.type === 'text')
                            .map((c) => (
                              <option key={c.id} value={c.id}>#{c.name}</option>
                            ))}
                        </select>
                      </div>
                    ) : (
                      <input
                        type={field.type}
                        value={createConfig[field.key] || ''}
                        onChange={(e) => setCreateConfig((prev) => ({ ...prev, [field.key]: e.target.value }))}
                        placeholder={field.placeholder}
                        className="terminal-input w-full"
                      />
                    )}
                  </div>
                ))}
                <div className="flex gap-2">
                  <button type="submit" className="terminal-button" disabled={loading || !createName.trim()}>
                    {loading ? '[CREATING...]' : '[SAVE]'}
                  </button>
                  <button
                    type="button"
                    onClick={() => { setShowCreate(false); setCreateName(''); setCreateDesc(''); setCreateType(''); setCreateConfig({}); setChannelServerId(''); }}
                    className="text-gb-fg-f hover:text-gb-aqua font-mono text-sm"
                  >
                    [CANCEL]
                  </button>
                </div>
              </form>
            )}
          </div>

          {/* Bot list */}
          {loading && bots.length === 0 && (
            <p className="text-gb-fg-f font-mono text-sm">[loading bots...]</p>
          )}
          {!loading && bots.length === 0 && (
            <p className="text-gb-fg-f font-mono text-sm">[no bots created yet]</p>
          )}

          <div className="space-y-3">
            {bots.map((bot) => (
              <div key={bot.id} className="border border-gb-bg-t p-4">
                {editingId === bot.id ? (
                  <form onSubmit={handleUpdate} className="space-y-3">
                    <div>
                      <label className="block text-gb-fg-f mb-1 font-mono text-xs">NAME:</label>
                      <input
                        type="text"
                        value={editName}
                        onChange={(e) => setEditName(e.target.value.slice(0, 32))}
                        maxLength={32}
                        className="terminal-input w-full"
                      />
                    </div>
                    <div>
                      <label className="block text-gb-fg-f mb-1 font-mono text-xs">DESCRIPTION:</label>
                      <input
                        type="text"
                        value={editDesc}
                        onChange={(e) => setEditDesc(e.target.value.slice(0, 256))}
                        maxLength={256}
                        className="terminal-input w-full"
                      />
                    </div>
                    <div className="flex gap-2">
                      <button type="submit" className="terminal-button text-xs" disabled={loading}>
                        {loading ? '[SAVING...]' : '[SAVE]'}
                      </button>
                      <button
                        type="button"
                        onClick={() => setEditingId(null)}
                        className="text-gb-fg-f hover:text-gb-aqua font-mono text-xs"
                      >
                        [CANCEL]
                      </button>
                    </div>
                  </form>
                ) : (
                  <>
                    <div className="flex items-start justify-between gap-2 mb-2">
                      <div className="min-w-0">
                        <p className="text-gb-green font-mono text-sm truncate">
                          {bot.avatar && (
                            <img
                              src={bot.avatar}
                              alt=""
                              className="inline w-5 h-5 mr-1 align-middle border border-gb-bg-t"
                            />
                          )}
                          [{bot.name}]
                          {bot.bot_type && (
                            <span className="text-gb-aqua text-xs ml-2">({BOT_TYPE_CONFIGS[bot.bot_type]?.label || bot.bot_type})</span>
                          )}
                        </p>
                        {bot.description && (
                          <p className="text-gb-fg-f font-mono text-xs mt-1 truncate">
                            {bot.description}
                          </p>
                        )}
                      </div>
                      <span className="text-gb-fg-f font-mono text-xs shrink-0">
                        ID:{bot.id.slice(0, 8)}
                      </span>
                    </div>
                    <div className="flex flex-wrap gap-2">
                      <button
                        type="button"
                        onClick={() => startEdit(bot)}
                        className="terminal-button text-xs"
                      >
                        [EDIT]
                      </button>
                      <button
                        type="button"
                        onClick={() => handleDelete(bot.id, bot.name)}
                        className="terminal-button text-xs hover:!text-gb-red"
                      >
                        [DELETE]
                      </button>
                      <button
                        type="button"
                        onClick={() => { setAddToServerBotId(bot.id); setSelectedServer(''); }}
                        className="terminal-button text-xs"
                      >
                        [ADD TO SERVER]
                      </button>
                      <button
                        type="button"
                        onClick={() => handleRegenerate(bot.id)}
                        className="terminal-button text-xs"
                      >
                        [REGENERATE TOKEN]
                      </button>
                      <Link
                        to={`/bots/${bot.id}/commands`}
                        className="terminal-button text-xs"
                      >
                        [COMMANDS]
                      </Link>
                    </div>
                  </>
                )}
              </div>
            ))}
          </div>

          {/* Add to server modal */}
          {addToServerBotId && (
            <div className="fixed inset-0 bg-black/60 flex items-center justify-center z-50">
              <div className="border border-gb-bg-t bg-gb-bg p-6 max-w-md w-full mx-4">
                <p className="text-gb-orange font-mono text-sm mb-4">
                  {'>'} ADD BOT TO SERVER
                </p>
                <select
                  value={selectedServer}
                  onChange={(e) => setSelectedServer(e.target.value)}
                  className="terminal-input w-full mb-4"
                >
                  <option value="">-- select server --</option>
                  {servers.map((s) => (
                    <option key={s.id} value={s.id}>{s.name}</option>
                  ))}
                </select>
                <div className="flex gap-2">
                  <button
                    type="button"
                    onClick={handleAddToServer}
                    className="terminal-button text-xs"
                    disabled={!selectedServer}
                  >
                    [ADD]
                  </button>
                  <button
                    type="button"
                    onClick={() => { setAddToServerBotId(null); setSelectedServer(''); }}
                    className="text-gb-fg-f hover:text-gb-aqua font-mono text-xs"
                  >
                    [CANCEL]
                  </button>
                </div>
              </div>
            </div>
          )}

          {/* Footer */}
          <div className="mt-6 pt-4 border-t border-gb-bg-t">
            <Link to="/bots" className="text-gb-fg-f hover:text-gb-aqua font-mono text-sm">
              {'<'} [BACK TO STORE]
            </Link>
          </div>
        </div>
      </div>
    </div>
  );
}
