/**
 * Create-telegram-bot dialog. Renders as a Radix Dialog triggered
 * by a Button. The form collects the bot fields, including the
 * one-time bot_token paste.
 *
 * The bot_token is write-only: the UI shows it as a password
 * field and never reads it back from the server. The operator
 * pastes a token they got from @BotFather; the server stores
 * the plaintext (so telegramd can use it) and bcrypt-hashes it
 * for the `bot_token_hash` column. After a successful create
 * the form clears the token field.
 *
 * Renders nothing if the user lacks create-bot permission
 * (super_admin only — see canManageTelegram in
 * web/src/lib/scope.ts).
 */

import { useEffect, useState } from 'react';
import { useForm } from 'react-hook-form';
import { zodResolver } from '@hookform/resolvers/zod';
import { z } from 'zod';
import { Eye, EyeOff, Plus, Send } from 'lucide-react';
import { toast } from 'sonner';

import { Button } from '@/components/ui/button';
import { Input } from '@/components/ui/input';
import { Label } from '@/components/ui/label';
import { Textarea } from '@/components/ui/textarea';
import {
  Dialog,
  DialogContent,
  DialogDescription,
  DialogFooter,
  DialogHeader,
  DialogTitle,
  DialogTrigger,
} from '@/components/ui/dialog';

import { getErrorMessage, useCreateTelegramBot } from './api';

const ID_RE = /^[a-z0-9][a-z0-9-]{0,62}[a-z0-9]$/;
// Telegram bot tokens look like `<bot_id>:<secret>` where
// bot_id is decimal digits and secret is 35+ [A-Za-z0-9_-]
// chars. We accept the same shape documented in
// M13b_PLAN §2.3.
const TOKEN_RE = /^\d+:[A-Za-z0-9_-]{35,}$/;

const formSchema = z.object({
  id: z
    .string()
    .min(2, 'Bot id must be 2–64 characters')
    .max(64, 'Bot id must be 2–64 characters')
    .regex(ID_RE, 'Lowercase letters, digits, and dashes only'),
  name: z.string().min(1, 'Name is required').max(200, 'Name must be \u2264 200 characters'),
  bot_token: z
    .string()
    .min(1, 'Bot token is required')
    .regex(TOKEN_RE, 'Token must look like 12345678:AbCdEfGh... (35+ chars after the colon)'),
  welcome_message: z
    .string()
    .max(4096, 'Welcome message must be \u2264 4096 characters')
    .optional()
    .or(z.literal('')),
  default_source_id: z
    .string()
    .regex(ID_RE, 'Lowercase letters, digits, and dashes only')
    .optional()
    .or(z.literal('')),
  description: z
    .string()
    .max(500, 'Description must be \u2264 500 characters')
    .optional()
    .or(z.literal('')),
});

type FormValues = z.infer<typeof formSchema>;

const EMPTY_DEFAULTS: FormValues = {
  id: '',
  name: '',
  bot_token: '',
  welcome_message: '',
  default_source_id: '',
  description: '',
};

export function CreateTelegramBotDialog({ tenantId }: { tenantId: string }) {
  const [open, setOpen] = useState(false);
  const [showToken, setShowToken] = useState(false);
  const create = useCreateTelegramBot(tenantId);

  const form = useForm<FormValues>({
    resolver: zodResolver(formSchema),
    defaultValues: EMPTY_DEFAULTS,
  });

  // Reset form when the dialog opens.
  useEffect(() => {
    if (open) form.reset(EMPTY_DEFAULTS);
  }, [open, form]);

  const onSubmit = form.handleSubmit(async (values) => {
    try {
      const created = await create.mutateAsync({
        id: values.id.trim(),
        name: values.name.trim(),
        bot_token: values.bot_token.trim(),
        welcome_message: values.welcome_message || undefined,
        default_source_id: values.default_source_id || undefined,
        description: values.description || undefined,
      });
      toast.success(`Bot "${created.name}" created.`);
      // Clear the token field on success; it has been stored
      // server-side and will never be re-shown.
      form.setValue('bot_token', '');
      setShowToken(false);
      setOpen(false);
    } catch (err) {
      toast.error(getErrorMessage(err));
    }
  });

  return (
    <Dialog open={open} onOpenChange={setOpen}>
      <DialogTrigger asChild>
        <Button>
          <Plus className="mr-2 h-4 w-4" />
          New bot
        </Button>
      </DialogTrigger>
      <DialogContent className="sm:max-w-lg">
        <DialogHeader>
          <DialogTitle className="flex items-center gap-2">
            <Send className="h-4 w-4" />
            New Telegram bot
          </DialogTitle>
          <DialogDescription>
            Paste a bot token from <strong>@BotFather</strong>. The token is
            stored encrypted server-side and never shown again after this
            dialog closes. telegramd will pick it up on its next reload.
          </DialogDescription>
        </DialogHeader>
        <form onSubmit={onSubmit} className="flex flex-col gap-4">
          <div className="grid grid-cols-2 gap-3">
            <div className="col-span-1 flex flex-col gap-1">
              <Label htmlFor="bot-id">ID</Label>
              <Input id="bot-id" placeholder="primary" {...form.register('id')} />
              {form.formState.errors.id ? (
                <p className="text-xs text-destructive">{form.formState.errors.id.message}</p>
              ) : null}
            </div>
            <div className="col-span-1 flex flex-col gap-1">
              <Label htmlFor="bot-name">Name</Label>
              <Input id="bot-name" placeholder="Acme Ops" {...form.register('name')} />
              {form.formState.errors.name ? (
                <p className="text-xs text-destructive">{form.formState.errors.name.message}</p>
              ) : null}
            </div>
          </div>
          <div className="flex flex-col gap-1">
            <Label htmlFor="bot-token">Bot token</Label>
            <div className="flex items-center gap-2">
              <Input
                id="bot-token"
                type={showToken ? 'text' : 'password'}
                placeholder="123456789:AbCdEfGhIjKlMnOpQrStUvWxYz-12345"
                autoComplete="off"
                spellCheck={false}
                {...form.register('bot_token')}
              />
              <Button
                type="button"
                variant="ghost"
                size="sm"
                onClick={() => setShowToken((v) => !v)}
                aria-label={showToken ? 'Hide token' : 'Show token'}
              >
                {showToken ? <EyeOff className="h-3 w-3" /> : <Eye className="h-3 w-3" />}
              </Button>
            </div>
            {form.formState.errors.bot_token ? (
              <p className="text-xs text-destructive">
                {form.formState.errors.bot_token.message}
              </p>
            ) : (
              <p className="text-xs text-muted-foreground">
                Get this from @BotFather in Telegram. The shape is
                <code className="ml-1 rounded bg-muted px-1 py-0.5 text-[10px]">
                  &lt;bot_id&gt;:&lt;secret&gt;
                </code>
                .
              </p>
            )}
          </div>
          <div className="flex flex-col gap-1">
            <Label htmlFor="bot-default-source">Default source ID (optional)</Label>
            <Input
              id="bot-default-source"
              placeholder="primary"
              {...form.register('default_source_id')}
            />
            <p className="text-xs text-muted-foreground">
              If set, the bot will be the default for alerts coming from this source.
            </p>
            {form.formState.errors.default_source_id ? (
              <p className="text-xs text-destructive">
                {form.formState.errors.default_source_id.message}
              </p>
            ) : null}
          </div>
          <div className="flex flex-col gap-1">
            <Label htmlFor="bot-welcome">Welcome message (optional)</Label>
            <Textarea
              id="bot-welcome"
              rows={2}
              placeholder="Welcome to Acme alerts! Reply /help to see available commands."
              {...form.register('welcome_message')}
            />
            <p className="text-xs text-muted-foreground">
              Sent in response to /start. M13c will wire this into telegramd.
            </p>
            {form.formState.errors.welcome_message ? (
              <p className="text-xs text-destructive">
                {form.formState.errors.welcome_message.message}
              </p>
            ) : null}
          </div>
          <div className="flex flex-col gap-1">
            <Label htmlFor="bot-desc">Description (optional)</Label>
            <Textarea
              id="bot-desc"
              rows={2}
              placeholder="What does this bot do?"
              {...form.register('description')}
            />
            {form.formState.errors.description ? (
              <p className="text-xs text-destructive">
                {form.formState.errors.description.message}
              </p>
            ) : null}
          </div>

          <DialogFooter>
            <Button type="button" variant="ghost" onClick={() => setOpen(false)}>
              Cancel
            </Button>
            <Button type="submit" disabled={create.isPending}>
              {create.isPending ? 'Creating…' : 'Create bot'}
            </Button>
          </DialogFooter>
        </form>
      </DialogContent>
    </Dialog>
  );
}
