import { useState, useEffect } from 'react';
import { toast } from 'sonner';
import { ChevronDown } from 'lucide-react';
import { Input } from '@/components/ui/input';
import { Label } from '@/components/ui/label';
import { Button } from '@/components/ui/button';
import { Collapsible, CollapsibleTrigger, CollapsibleContent } from '@/components/ui/collapsible';
import { useClient } from 'hooks/useClient';

type DiscordConfig = {
  configured: boolean;
  enabled: boolean;
  botToken: string | null;
  serverInvite: string | null;
  botHandle: string | null;
};

type DiscordStatus = {
  configured: boolean;
  enabled: boolean;
  running: boolean;
  botUsername: string | null;
};

const SetupGuide = () => {
  const [open, setOpen] = useState(false);

  return (
    <Collapsible open={open} onOpenChange={setOpen}>
      <CollapsibleTrigger className="flex items-center gap-2 text-sm font-medium text-duck-teal cursor-pointer hover:underline w-full">
        <ChevronDown className={`h-3.5 w-3.5 transition-transform duration-200 ${open ? 'rotate-180' : ''}`} />
        Step-by-step setup guide
      </CollapsibleTrigger>
      <CollapsibleContent>
        <ol className="mt-3 grid gap-4 text-sm text-duck-dark/70 dark:text-foreground/70 list-decimal list-outside pl-5">
          <li>
            <strong className="text-duck-dark dark:text-foreground">Create a Discord application</strong>
            <p className="mt-1">
              Go to the{' '}
              <a href="https://discord.com/developers/applications" target="_blank" rel="noopener noreferrer" className="text-duck-teal underline">
                Discord Developer Portal
              </a>{' '}
              and click <strong>New Application</strong>.
            </p>
            <ul className="mt-1 list-disc list-outside pl-5 grid gap-0.5">
              <li>Fill in <strong>Name</strong> (e.g. &quot;Officer&quot;), optionally a <strong>Description</strong> and <strong>Tags</strong></li>
              <li>Leave everything else empty — <strong>Interactions Endpoint URL</strong>, <strong>Linked Roles Verification URL</strong>, and <strong>Terms of Service / Privacy Policy URLs</strong> are not needed</li>
            </ul>
            <p className="mt-1">Click <strong>Create</strong>.</p>
            <p className="mt-2 text-xs text-duck-dark/50 dark:text-foreground/50">
              You will see an Application ID and Public Key on this page — you can ignore both. Our bot connects via the gateway (WebSocket), not webhooks, so these are not used.
            </p>
          </li>

          <li>
            <strong className="text-duck-dark dark:text-foreground">Go to the Bot page</strong>
            <p className="mt-1">
              In the left sidebar, click <strong>Bot</strong>. A bot user is created automatically with your application.
              You can optionally set a custom username and avatar here — this is what users will see when they DM the bot.
            </p>
          </li>

          <li>
            <strong className="text-duck-dark dark:text-foreground">Enable privileged intents</strong>
            <p className="mt-1">
              Still on the <strong>Bot</strong> page, scroll down to <strong>Privileged Gateway Intents</strong> and enable:
            </p>
            <ul className="mt-1 list-disc list-outside pl-5 grid gap-0.5">
              <li><strong>Presence Intent</strong> — shows the bot as online in your server</li>
              <li><strong>Server Members Intent</strong> — makes the bot visible in the member list so users can find and DM it</li>
              <li><strong>Message Content Intent</strong> — required to read DM message text</li>
            </ul>
            <p className="mt-1">Click <strong>Save Changes</strong>.</p>
          </li>

          <li>
            <strong className="text-duck-dark dark:text-foreground">Copy the bot token</strong>
            <p className="mt-1">
              On the <strong>Bot</strong> page, click <strong>Reset Token</strong> (or <strong>View Token</strong> if this is a new bot).
              Copy the token — you will only see it once.
            </p>
            <p className="mt-2 text-xs text-duck-dark/50 dark:text-foreground/50">
              Keep this token secret. Anyone with this token can control your bot. If it leaks, reset it immediately from this page.
            </p>
          </li>

          <li>
            <strong className="text-duck-dark dark:text-foreground">Invite the bot to your server (optional)</strong>
            <p className="mt-1">
              Open this URL in your browser, replacing{' '}
              <code className="text-xs bg-duck-dark/5 dark:bg-foreground/5 px-1.5 py-0.5 rounded">YOUR_APP_ID</code>{' '}
              with the Application ID from the <strong>General Information</strong> page:
            </p>
            <code className="mt-1.5 block text-xs bg-duck-dark/5 dark:bg-foreground/5 px-3 py-2 rounded break-all">
              https://discord.com/oauth2/authorize?client_id=YOUR_APP_ID&amp;scope=bot&amp;permissions=0
            </code>
            <p className="mt-1.5">
              Select your server and click <strong>Authorize</strong>. No bot permissions are needed — leave them at zero.
            </p>
            <p className="mt-2 text-xs text-duck-dark/50 dark:text-foreground/50">
              Adding the bot to a shared server is optional but has a few advantages:
            </p>
            <ul className="mt-1 text-xs text-duck-dark/50 dark:text-foreground/50 list-disc list-outside pl-5 grid gap-0.5">
              <li>Users can find the bot in the member list and right-click → <strong>Message</strong> to start a DM</li>
              <li>The bot shows as online in the server, so users can see at a glance whether it&apos;s running</li>
              <li>Easier onboarding — you can pin the pairing instructions in a channel for your team</li>
            </ul>
            <p className="mt-1 text-xs text-duck-dark/50 dark:text-foreground/50">
              Without a shared server, users can still DM the bot by searching its exact username — but a shared server makes discovery much simpler.
            </p>
          </li>

          <li>
            <strong className="text-duck-dark dark:text-foreground">Paste the token below and save</strong>
            <p className="mt-1">
              Paste the bot token into the field below and click <strong>Save</strong>.
              The bot will come online automatically. Users can then link their Discord accounts from their personal integration settings.
            </p>
          </li>
        </ol>
      </CollapsibleContent>
    </Collapsible>
  );
};

export const DiscordBotConfig = () => {
  const client = useClient();
  const [isLoading, setIsLoading] = useState(true);
  const [isSaving, setIsSaving] = useState(false);
  const [botToken, setBotToken] = useState('');
  const [serverInvite, setServerInvite] = useState('');
  const [botHandle, setBotHandle] = useState('');
  const [status, setStatus] = useState<DiscordStatus | null>(null);

  const fetchStatus = () => {
    client
      .get<DiscordStatus>('/channels/discord/status')
      .then(setStatus)
      .catch(() => {});
  };

  useEffect(() => {
    Promise.all([
      client.get<DiscordConfig>('/channels/discord/config').then((data) => {
        if (data.botToken) setBotToken(data.botToken);
        if (data.serverInvite) setServerInvite(data.serverInvite);
        if (data.botHandle) setBotHandle(data.botHandle);
      }),
      client.get<DiscordStatus>('/channels/discord/status').then(setStatus),
    ])
      .catch(() => {})
      .finally(() => setIsLoading(false));
  }, []);

  const handleSave = async () => {
    if (isSaving) return;
    setIsSaving(true);
    try {
      await client.put('/channels/discord/config', {
        botToken: botToken.trim(),
        serverInvite: serverInvite.trim() || undefined,
        botHandle: botHandle.trim() || undefined,
      });
      toast.success('Discord bot configuration saved');
      fetchStatus();
    } catch {
      toast.error('Failed to save Discord bot configuration');
    } finally {
      setIsSaving(false);
    }
  };

  if (isLoading) return null;

  return (
    <div className="grid gap-5">
      {status && (
        <div className="flex items-center gap-2 rounded-lg border border-duck-dark/10 dark:border-foreground/10 p-3">
          <div className={`h-2.5 w-2.5 rounded-full shrink-0 ${status.running ? 'bg-green-500' : 'bg-duck-dark/20 dark:bg-foreground/20'}`} />
          <span className="text-sm text-duck-dark dark:text-foreground">
            {status.running ? `Online as ${status.botUsername}` : status.configured ? 'Bot configured but not running' : 'Not configured'}
          </span>
        </div>
      )}

      <SetupGuide />

      <div className="border-t border-duck-dark/10 dark:border-foreground/10 pt-5 grid gap-5">
        <Label className="grid gap-2">
          <span className="text-duck-dark/70 dark:text-foreground/70">Bot Token</span>
          <Input
            className="h-11 bg-background/60 border-duck-dark/20 text-duck-dark placeholder:text-duck-dark/40"
            type="password"
            value={botToken}
            onChange={(ev) => setBotToken(ev.target.value)}
            placeholder="MTIz..."
          />
        </Label>

        <Label className="grid gap-2">
          <span className="text-duck-dark/70 dark:text-foreground/70">Server Invite Link</span>
          <Input
            className="h-11 bg-background/60 border-duck-dark/20 text-duck-dark placeholder:text-duck-dark/40"
            value={serverInvite}
            onChange={(ev) => setServerInvite(ev.target.value)}
            placeholder="https://discord.gg/..."
          />
          <span className="text-xs text-duck-dark/40 dark:text-foreground/40">
            Shown to users so they can join the server and find the bot.
          </span>
        </Label>

        <Label className="grid gap-2">
          <span className="text-duck-dark/70 dark:text-foreground/70">Bot Handle</span>
          <Input
            className="h-11 bg-background/60 border-duck-dark/20 text-duck-dark placeholder:text-duck-dark/40"
            value={botHandle}
            onChange={(ev) => setBotHandle(ev.target.value)}
            placeholder="my-bot#1234"
          />
          <span className="text-xs text-duck-dark/40 dark:text-foreground/40">
            The bot&apos;s username#discriminator — shown to users who want to DM the bot directly.
          </span>
        </Label>

        <Button
          type="button"
          onClick={handleSave}
          disabled={isSaving || !botToken.trim()}
          className="w-full h-11 bg-duck-yellow hover:bg-duck-yellow/90 text-duck-teal font-bold transition-all duration-200 hover:scale-105 cursor-pointer disabled:opacity-50 disabled:hover:scale-100"
        >
          {isSaving ? 'Saving...' : 'Save'}
        </Button>
      </div>
    </div>
  );
};
