'use client';

import {
  componentsV2HasContent,
  embedHasContent,
  type MessageComponentsV2,
  type TagDashboard,
  type TagResponseType,
  type WelcomeEmbed
} from '@nexumi/shared';
import { Plus, Trash2 } from 'lucide-react';
import { useState } from 'react';
import { toast } from 'sonner';
import { FieldAnchor } from '@/components/layout/field-anchor';
import { useTranslations } from '@/components/locale-provider';
import { Button } from '@/components/ui/button';
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card';
import { DiscordChannelMultiSelect } from '@/components/ui/discord-channel-select';
import {
  DiscordComponentsV2Builder,
  normalizeComponentsV2
} from '@/components/ui/discord-components-v2-builder';
import { DiscordEmbedBuilder, normalizeEmbed } from '@/components/ui/discord-embed-builder';
import { DiscordRoleMultiSelect } from '@/components/ui/discord-role-select';
import { Input } from '@/components/ui/input';
import { Label } from '@/components/ui/label';
import { PlaceholderHelp } from '@/components/ui/placeholder-help';
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select';
import { Textarea } from '@/components/ui/textarea';

const RESPONSE_TYPES: TagResponseType[] = ['TEXT', 'EMBED', 'COMPONENTS_V2'];

interface LocalTag extends TagDashboard {
  clientKey: string;
  saving?: boolean;
}

const EMPTY_DRAFT = {
  name: '',
  content: '',
  embed: null as WelcomeEmbed | null,
  components: null as MessageComponentsV2 | null,
  responseType: 'TEXT' as TagResponseType,
  triggerWord: '',
  cooldownSeconds: 15,
  allowedRoleIds: [] as string[],
  allowedChannelIds: [] as string[]
};

interface TagsManagerProps {
  guildId: string;
  initialTags: TagDashboard[];
}

export function TagsManager({ guildId, initialTags }: TagsManagerProps) {
  const t = useTranslations();
  const [tags, setTags] = useState<LocalTag[]>(
    initialTags.map((tag, index) => ({
      ...tag,
      cooldownSeconds: tag.cooldownSeconds ?? 15,
      embed: tag.embed ?? null,
      components: tag.components ?? null,
      clientKey: tag.id ?? `existing-${index}`
    }))
  );
  const [draft, setDraft] = useState(EMPTY_DRAFT);
  const [creating, setCreating] = useState(false);

  function validateTagPayload(responseType: TagResponseType, embed: WelcomeEmbed | null, components: MessageComponentsV2 | null) {
    const normalizedEmbed = responseType === 'EMBED' ? normalizeEmbed(embed) : null;
    const normalizedComponents = responseType === 'COMPONENTS_V2' ? normalizeComponentsV2(components) : null;

    if (responseType === 'EMBED' && !embedHasContent(normalizedEmbed) && normalizedEmbed?.color === undefined) {
      toast.error(t('modulePages.tags.embedRequired'));
      return null;
    }
    if (responseType === 'COMPONENTS_V2' && !componentsV2HasContent(normalizedComponents)) {
      toast.error(t('modulePages.tags.componentsRequired'));
      return null;
    }
    return { embed: normalizedEmbed, components: normalizedComponents };
  }

  async function handleCreate() {
    if (!draft.name.trim()) {
      toast.error(t('modulePages.tags.nameRequired'));
      return;
    }
    const validated = validateTagPayload(draft.responseType, draft.embed, draft.components);
    if (!validated) {
      return;
    }
    setCreating(true);
    try {
      const response = await fetch(`/api/guilds/${guildId}/tags`, {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({
          name: draft.name.trim(),
          content: draft.responseType === 'TEXT' ? draft.content.trim() || null : null,
          embed: validated.embed,
          components: validated.components,
          responseType: draft.responseType,
          triggerWord: draft.triggerWord.trim() || null,
          cooldownSeconds: draft.cooldownSeconds,
          allowedRoleIds: draft.allowedRoleIds,
          allowedChannelIds: draft.allowedChannelIds
        })
      });
      const body = (await response.json().catch(() => null)) as (TagDashboard & { error?: string }) | null;
      if (!response.ok || !body) {
        toast.error(body?.error ?? t('common.saveError'));
        return;
      }
      setTags((prev) => [
        {
          ...body,
          clientKey: body.id ?? `new-${Date.now()}`
        },
        ...prev
      ]);
      setDraft(EMPTY_DRAFT);
      toast.success(t('common.saveSuccess'));
    } catch {
      toast.error(t('common.saveError'));
    } finally {
      setCreating(false);
    }
  }

  async function handleSave(tag: LocalTag) {
    const validated = validateTagPayload(tag.responseType, tag.embed ?? null, tag.components ?? null);
    if (!validated) {
      return;
    }
    setTags((prev) => prev.map((entry) => (entry.clientKey === tag.clientKey ? { ...entry, saving: true } : entry)));
    try {
      const response = await fetch(`/api/guilds/${guildId}/tags/${tag.id}`, {
        method: 'PATCH',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({
          name: tag.name,
          content: tag.responseType === 'TEXT' ? tag.content : null,
          embed: validated.embed,
          components: validated.components,
          responseType: tag.responseType,
          triggerWord: tag.triggerWord,
          cooldownSeconds: tag.cooldownSeconds,
          allowedRoleIds: tag.allowedRoleIds,
          allowedChannelIds: tag.allowedChannelIds
        })
      });
      const body = (await response.json().catch(() => null)) as (TagDashboard & { error?: string }) | null;
      if (!response.ok || !body) {
        toast.error(body?.error ?? t('common.saveError'));
        setTags((prev) =>
          prev.map((entry) => (entry.clientKey === tag.clientKey ? { ...entry, saving: false } : entry))
        );
        return;
      }
      setTags((prev) =>
        prev.map((entry) =>
          entry.clientKey === tag.clientKey ? { ...entry, ...body, clientKey: entry.clientKey, saving: false } : entry
        )
      );
      toast.success(t('common.saveSuccess'));
    } catch {
      toast.error(t('common.saveError'));
      setTags((prev) => prev.map((entry) => (entry.clientKey === tag.clientKey ? { ...entry, saving: false } : entry)));
    }
  }

  async function handleDelete(tag: LocalTag) {
    if (!window.confirm(t('modulePages.tags.confirmDelete'))) {
      return;
    }
    try {
      const response = await fetch(`/api/guilds/${guildId}/tags/${tag.id}`, { method: 'DELETE' });
      if (!response.ok) {
        toast.error(t('common.saveError'));
        return;
      }
      setTags((prev) => prev.filter((entry) => entry.clientKey !== tag.clientKey));
      toast.success(t('common.saveSuccess'));
    } catch {
      toast.error(t('common.saveError'));
    }
  }

  function renderResponseEditor(
    responseType: TagResponseType,
    embed: WelcomeEmbed | null,
    components: MessageComponentsV2 | null,
    content: string,
    onEmbedChange: (embed: WelcomeEmbed | null) => void,
    onComponentsChange: (components: MessageComponentsV2 | null) => void,
    onContentChange: (content: string) => void
  ) {
    if (responseType === 'TEXT') {
      return (
        <div className="space-y-2">
          <Label>{t('modulePages.tags.content')}</Label>
          <Textarea rows={3} value={content} onChange={(event) => onContentChange(event.target.value)} />
          <PlaceholderHelp preset="tags" />
        </div>
      );
    }
    if (responseType === 'EMBED') {
      return (
        <div className="space-y-2">
          <Label>{t('modulePages.tags.embed')}</Label>
          <DiscordEmbedBuilder value={embed} onChange={onEmbedChange} placeholderPreset="tags" />
        </div>
      );
    }
    return (
      <div className="space-y-2">
        <Label>{t('modulePages.tags.components')}</Label>
        <DiscordComponentsV2Builder
          guildId={guildId}
          value={components}
          onChange={onComponentsChange}
          placeholderPreset="tags"
        />
      </div>
    );
  }

  return (
    <div className="space-y-6">
      <FieldAnchor id="field-tags-create">
      <Card>
        <CardHeader>
          <CardTitle>{t('modulePages.tags.createTitle')}</CardTitle>
          <CardDescription>{t('modulePages.tags.createDescription')}</CardDescription>
        </CardHeader>
        <CardContent className="space-y-4">
          <div className="grid gap-4 sm:grid-cols-2">
            <div className="space-y-2">
              <Label>{t('modulePages.tags.name')}</Label>
              <Input value={draft.name} onChange={(event) => setDraft((prev) => ({ ...prev, name: event.target.value }))} />
            </div>
            <div className="space-y-2">
              <Label>{t('modulePages.tags.responseType')}</Label>
              <Select value={draft.responseType} onValueChange={(value) => setDraft((prev) => ({ ...prev, responseType: value as TagResponseType }))}>
                <SelectTrigger>
                  <SelectValue />
                </SelectTrigger>
                <SelectContent>
                  {RESPONSE_TYPES.map((type) => (
                    <SelectItem key={type} value={type}>
                      {t(`modulePages.tags.responseTypes.${type}`)}
                    </SelectItem>
                  ))}
                </SelectContent>
              </Select>
            </div>
            <div className="space-y-2">
              <Label>{t('modulePages.tags.triggerWord')}</Label>
              <Input value={draft.triggerWord} onChange={(event) => setDraft((prev) => ({ ...prev, triggerWord: event.target.value }))} placeholder={t('common.optional')} />
            </div>
            <div className="space-y-2">
              <Label>{t('modulePages.tags.cooldownSeconds')}</Label>
              <Input
                type="number"
                min={0}
                max={3600}
                value={draft.cooldownSeconds}
                onChange={(event) =>
                  setDraft((prev) => ({
                    ...prev,
                    cooldownSeconds: Math.min(3600, Math.max(0, Number(event.target.value) || 0))
                  }))
                }
              />
              <p className="text-xs text-muted-foreground">{t('modulePages.tags.cooldownHint')}</p>
            </div>
          </div>
          {renderResponseEditor(
            draft.responseType,
            draft.embed,
            draft.components,
            draft.content,
            (embed) => setDraft((prev) => ({ ...prev, embed })),
            (components) => setDraft((prev) => ({ ...prev, components })),
            (content) => setDraft((prev) => ({ ...prev, content }))
          )}
          <div className="grid gap-4 sm:grid-cols-2">
            <div className="space-y-2">
              <Label>{t('modulePages.tags.allowedRoleIds')}</Label>
              <DiscordRoleMultiSelect
                guildId={guildId}
                value={draft.allowedRoleIds}
                onChange={(allowedRoleIds) => setDraft((prev) => ({ ...prev, allowedRoleIds }))}
              />
            </div>
            <div className="space-y-2">
              <Label>{t('modulePages.tags.allowedChannelIds')}</Label>
              <DiscordChannelMultiSelect
                guildId={guildId}
                value={draft.allowedChannelIds}
                onChange={(allowedChannelIds) => setDraft((prev) => ({ ...prev, allowedChannelIds }))}
              />
            </div>
          </div>
          <Button type="button" onClick={handleCreate} disabled={creating}>
            <Plus className="size-4" />
            {creating ? t('common.saving') : t('modulePages.tags.create')}
          </Button>
        </CardContent>
      </Card>
      </FieldAnchor>

      <FieldAnchor id="field-tags-list">
      <Card>
        <CardHeader>
          <CardTitle>{t('modulePages.tags.listTitle')}</CardTitle>
          <CardDescription>{t('modulePages.tags.listDescription')}</CardDescription>
        </CardHeader>
        <CardContent className="space-y-4">
          {tags.length === 0 && <p className="text-sm text-muted-foreground">{t('modulePages.tags.empty')}</p>}
          {tags.map((tag) => (
            <div key={tag.clientKey} className="space-y-3 rounded-md border border-border p-4">
              <div className="grid gap-3 sm:grid-cols-3">
                <div className="space-y-2">
                  <Label>{t('modulePages.tags.name')}</Label>
                  <Input value={tag.name} onChange={(event) => setTags((prev) => prev.map((entry) => (entry.clientKey === tag.clientKey ? { ...entry, name: event.target.value } : entry)))} />
                </div>
                <div className="space-y-2">
                  <Label>{t('modulePages.tags.responseType')}</Label>
                  <Select value={tag.responseType} onValueChange={(value) => setTags((prev) => prev.map((entry) => (entry.clientKey === tag.clientKey ? { ...entry, responseType: value as TagResponseType } : entry)))}>
                    <SelectTrigger>
                      <SelectValue />
                    </SelectTrigger>
                    <SelectContent>
                      {RESPONSE_TYPES.map((type) => (
                        <SelectItem key={type} value={type}>
                          {t(`modulePages.tags.responseTypes.${type}`)}
                        </SelectItem>
                      ))}
                    </SelectContent>
                  </Select>
                </div>
                <div className="space-y-2">
                  <Label>{t('modulePages.tags.triggerWord')}</Label>
                  <Input value={tag.triggerWord ?? ''} onChange={(event) => setTags((prev) => prev.map((entry) => (entry.clientKey === tag.clientKey ? { ...entry, triggerWord: event.target.value || null } : entry)))} />
                </div>
                <div className="space-y-2">
                  <Label>{t('modulePages.tags.cooldownSeconds')}</Label>
                  <Input
                    type="number"
                    min={0}
                    max={3600}
                    value={tag.cooldownSeconds}
                    onChange={(event) =>
                      setTags((prev) =>
                        prev.map((entry) =>
                          entry.clientKey === tag.clientKey
                            ? {
                                ...entry,
                                cooldownSeconds: Math.min(3600, Math.max(0, Number(event.target.value) || 0))
                              }
                            : entry
                        )
                      )
                    }
                  />
                  <p className="text-xs text-muted-foreground">{t('modulePages.tags.cooldownHint')}</p>
                </div>
              </div>
              {renderResponseEditor(
                tag.responseType,
                tag.embed ?? null,
                tag.components ?? null,
                tag.content ?? '',
                (embed) =>
                  setTags((prev) =>
                    prev.map((entry) => (entry.clientKey === tag.clientKey ? { ...entry, embed } : entry))
                  ),
                (components) =>
                  setTags((prev) =>
                    prev.map((entry) => (entry.clientKey === tag.clientKey ? { ...entry, components } : entry))
                  ),
                (content) =>
                  setTags((prev) =>
                    prev.map((entry) => (entry.clientKey === tag.clientKey ? { ...entry, content } : entry))
                  )
              )}
              <div className="grid gap-3 sm:grid-cols-2">
                <div className="space-y-2">
                  <Label>{t('modulePages.tags.allowedRoleIds')}</Label>
                  <DiscordRoleMultiSelect
                    guildId={guildId}
                    value={tag.allowedRoleIds}
                    onChange={(allowedRoleIds) =>
                      setTags((prev) =>
                        prev.map((entry) => (entry.clientKey === tag.clientKey ? { ...entry, allowedRoleIds } : entry))
                      )
                    }
                  />
                </div>
                <div className="space-y-2">
                  <Label>{t('modulePages.tags.allowedChannelIds')}</Label>
                  <DiscordChannelMultiSelect
                    guildId={guildId}
                    value={tag.allowedChannelIds}
                    onChange={(allowedChannelIds) =>
                      setTags((prev) =>
                        prev.map((entry) => (entry.clientKey === tag.clientKey ? { ...entry, allowedChannelIds } : entry))
                      )
                    }
                  />
                </div>
              </div>
              <div className="flex justify-end gap-2">
                <Button type="button" variant="outline" disabled={tag.saving} onClick={() => handleSave(tag)}>
                  {tag.saving ? t('common.saving') : t('common.save')}
                </Button>
                <Button type="button" variant="ghost" size="icon" aria-label={t('common.remove')} onClick={() => handleDelete(tag)}>
                  <Trash2 className="size-4" />
                </Button>
              </div>
            </div>
          ))}
        </CardContent>
      </Card>
      </FieldAnchor>
    </div>
  );
}
