'use client';

import { embedHasContent, type WelcomeEmbed } from '@nexumi/shared';
import { ChevronDown } from 'lucide-react';
import { useId, useState } from 'react';
import { useTranslations } from '@/components/locale-provider';
import { Input } from '@/components/ui/input';
import { Label } from '@/components/ui/label';
import { PlaceholderHelp } from '@/components/ui/placeholder-help';
import { Switch } from '@/components/ui/switch';
import { Textarea } from '@/components/ui/textarea';
import type { PlaceholderPresetId } from '@/lib/placeholder-presets';
import { cn } from '@/lib/utils';

export const DEFAULT_EMBED_COLOR = 0x6366f1;

function trimOrUndefined(value: string | undefined): string | undefined {
  const trimmed = value?.trim();
  return trimmed ? trimmed : undefined;
}

export function emptyEmbed(): WelcomeEmbed {
  return {
    title: '',
    description: '',
    color: DEFAULT_EMBED_COLOR,
    url: '',
    authorName: '',
    authorIconUrl: '',
    authorUrl: '',
    thumbnailUrl: '',
    imageUrl: '',
    footerText: '',
    footerIconUrl: '',
    timestamp: false
  };
}

export function normalizeEmbed(value: WelcomeEmbed | null | undefined): WelcomeEmbed | null {
  if (!value) {
    return null;
  }
  const normalized: WelcomeEmbed = {
    title: trimOrUndefined(value.title),
    description: trimOrUndefined(value.description),
    url: trimOrUndefined(value.url),
    color: typeof value.color === 'number' && Number.isFinite(value.color) ? value.color : undefined,
    authorName: trimOrUndefined(value.authorName),
    authorIconUrl: trimOrUndefined(value.authorIconUrl),
    authorUrl: trimOrUndefined(value.authorUrl),
    thumbnailUrl: trimOrUndefined(value.thumbnailUrl),
    imageUrl: trimOrUndefined(value.imageUrl),
    footerText: trimOrUndefined(value.footerText),
    footerIconUrl: trimOrUndefined(value.footerIconUrl),
    timestamp: value.timestamp ? true : undefined
  };
  if (!embedHasContent(normalized) && normalized.color === undefined) {
    return null;
  }
  return normalized;
}

export function embedFromUnknown(raw: unknown): WelcomeEmbed | null {
  if (!raw || typeof raw !== 'object' || Array.isArray(raw)) {
    return null;
  }
  const record = raw as Record<string, unknown>;
  return normalizeEmbed({
    title: typeof record.title === 'string' ? record.title : undefined,
    description: typeof record.description === 'string' ? record.description : undefined,
    url: typeof record.url === 'string' ? record.url : undefined,
    color: typeof record.color === 'number' ? record.color : undefined,
    authorName: typeof record.authorName === 'string' ? record.authorName : undefined,
    authorIconUrl: typeof record.authorIconUrl === 'string' ? record.authorIconUrl : undefined,
    authorUrl: typeof record.authorUrl === 'string' ? record.authorUrl : undefined,
    thumbnailUrl: typeof record.thumbnailUrl === 'string' ? record.thumbnailUrl : undefined,
    imageUrl: typeof record.imageUrl === 'string' ? record.imageUrl : undefined,
    footerText: typeof record.footerText === 'string' ? record.footerText : undefined,
    footerIconUrl: typeof record.footerIconUrl === 'string' ? record.footerIconUrl : undefined,
    timestamp: typeof record.timestamp === 'boolean' ? record.timestamp : undefined
  });
}

function colorToHex(color: number | undefined): string {
  const value = typeof color === 'number' && Number.isFinite(color) ? color : DEFAULT_EMBED_COLOR;
  return `#${Math.max(0, Math.min(0xffffff, Math.trunc(value))).toString(16).padStart(6, '0')}`;
}

function hexToColor(hex: string): number {
  const cleaned = hex.replace('#', '').trim();
  const parsed = Number.parseInt(cleaned, 16);
  return Number.isFinite(parsed) ? parsed : DEFAULT_EMBED_COLOR;
}

function applyPreviewVars(template: string, vars: Record<string, string>): string {
  const withVars = Object.entries(vars).reduce(
    (acc, [key, value]) => acc.replaceAll(`{${key}}`, value),
    template
  );
  return withVars.replace(/\["(\d{17,20})"\]/g, '#$1').replace(/<#(\d{17,20})>/g, '#$1');
}

function previewUrl(value: string | undefined, vars: Record<string, string>): string | undefined {
  if (!value?.trim()) {
    return undefined;
  }
  const rendered = applyPreviewVars(value, vars).trim();
  if (!/^https?:\/\//i.test(rendered)) {
    return undefined;
  }
  return rendered;
}

interface DiscordEmbedBuilderProps {
  value: WelcomeEmbed | null;
  onChange: (next: WelcomeEmbed | null) => void;
  className?: string;
  previewVars?: Record<string, string>;
  showClearHint?: boolean;
  placeholderPreset?: PlaceholderPresetId;
  titlePlaceholder?: string;
  descriptionPlaceholder?: string;
}

export function DiscordEmbedBuilder({
  value,
  onChange,
  className,
  previewVars,
  showClearHint = true,
  placeholderPreset = 'welcome',
  titlePlaceholder,
  descriptionPlaceholder
}: DiscordEmbedBuilderProps) {
  const t = useTranslations();
  const advancedId = useId();
  const [advancedOpen, setAdvancedOpen] = useState(false);
  const draft = value ?? emptyEmbed();
  const vars = previewVars ?? {};
  const colorHex = colorToHex(draft.color);

  const previewAuthor = draft.authorName ? applyPreviewVars(draft.authorName, vars) : '';
  const previewTitle = draft.title
    ? applyPreviewVars(draft.title, vars)
    : t('embedBuilder.previewTitlePlaceholder');
  const previewDescription = draft.description
    ? applyPreviewVars(draft.description, vars)
    : t('embedBuilder.previewDescriptionPlaceholder');
  const previewFooter = draft.footerText ? applyPreviewVars(draft.footerText, vars) : '';
  const authorIcon = previewUrl(draft.authorIconUrl, vars);
  const thumbnail = previewUrl(draft.thumbnailUrl, vars) ?? previewUrl(vars['user.avatar'], {});
  const image = previewUrl(draft.imageUrl, vars);
  const footerIcon = previewUrl(draft.footerIconUrl, vars);
  const hasContent = embedHasContent(draft) || Boolean(draft.color !== undefined);

  function patch(next: Partial<WelcomeEmbed>) {
    onChange({
      ...draft,
      ...next
    });
  }

  return (
    <div className={cn('grid gap-4 lg:grid-cols-2', className)}>
      <div className="space-y-3">
        <div className="space-y-2">
          <Label htmlFor="embed-title">{t('embedBuilder.title')}</Label>
          <Input
            id="embed-title"
            value={draft.title ?? ''}
            maxLength={256}
            placeholder={titlePlaceholder ?? t('embedBuilder.titlePlaceholder')}
            onChange={(event) => patch({ title: event.target.value })}
          />
        </div>
        <div className="space-y-2">
          <Label htmlFor="embed-description">{t('embedBuilder.description')}</Label>
          <Textarea
            id="embed-description"
            rows={5}
            maxLength={4096}
            value={draft.description ?? ''}
            placeholder={descriptionPlaceholder ?? t('embedBuilder.descriptionPlaceholder')}
            onChange={(event) => patch({ description: event.target.value })}
          />
        </div>
        <div className="space-y-2">
          <Label htmlFor="embed-color">{t('embedBuilder.color')}</Label>
          <div className="flex items-center gap-2">
            <input
              id="embed-color"
              type="color"
              className="size-9 cursor-pointer rounded-md border border-input bg-transparent p-1"
              value={colorHex}
              onChange={(event) => patch({ color: hexToColor(event.target.value) })}
            />
            <Input
              value={colorHex.toUpperCase()}
              maxLength={7}
              className="font-mono uppercase"
              onChange={(event) => {
                const next = event.target.value.trim();
                if (/^#[0-9A-Fa-f]{6}$/.test(next)) {
                  patch({ color: hexToColor(next) });
                }
              }}
            />
          </div>
        </div>

        <div className="rounded-md border border-border">
          <button
            type="button"
            className="flex w-full items-center justify-between gap-2 px-3 py-2 text-left text-xs font-medium text-muted-foreground hover:text-foreground"
            aria-expanded={advancedOpen}
            aria-controls={advancedId}
            onClick={() => setAdvancedOpen((prev) => !prev)}
          >
            <span>{t('embedBuilder.advancedToggle')}</span>
            <ChevronDown className={cn('size-4 shrink-0 transition-transform', advancedOpen && 'rotate-180')} />
          </button>
          {advancedOpen ? (
            <div id={advancedId} className="space-y-4 border-t border-border px-3 py-3">
              <div className="space-y-2">
                <p className="text-xs font-medium text-foreground">{t('embedBuilder.authorSection')}</p>
                <Input
                  value={draft.authorName ?? ''}
                  maxLength={256}
                  placeholder={t('embedBuilder.authorNamePlaceholder')}
                  onChange={(event) => patch({ authorName: event.target.value })}
                />
                <Input
                  value={draft.authorIconUrl ?? ''}
                  placeholder={t('embedBuilder.authorIconPlaceholder')}
                  onChange={(event) => patch({ authorIconUrl: event.target.value })}
                />
                <Input
                  value={draft.authorUrl ?? ''}
                  placeholder={t('embedBuilder.authorUrlPlaceholder')}
                  onChange={(event) => patch({ authorUrl: event.target.value })}
                />
              </div>

              <div className="space-y-2">
                <p className="text-xs font-medium text-foreground">{t('embedBuilder.mediaSection')}</p>
                <Input
                  value={draft.thumbnailUrl ?? ''}
                  placeholder={t('embedBuilder.thumbnailPlaceholder')}
                  onChange={(event) => patch({ thumbnailUrl: event.target.value })}
                />
                <Input
                  value={draft.imageUrl ?? ''}
                  placeholder={t('embedBuilder.imagePlaceholder')}
                  onChange={(event) => patch({ imageUrl: event.target.value })}
                />
                <Input
                  value={draft.url ?? ''}
                  placeholder={t('embedBuilder.titleUrlPlaceholder')}
                  onChange={(event) => patch({ url: event.target.value })}
                />
              </div>

              <div className="space-y-2">
                <p className="text-xs font-medium text-foreground">{t('embedBuilder.footerSection')}</p>
                <Input
                  value={draft.footerText ?? ''}
                  maxLength={2048}
                  placeholder={t('embedBuilder.footerTextPlaceholder')}
                  onChange={(event) => patch({ footerText: event.target.value })}
                />
                <Input
                  value={draft.footerIconUrl ?? ''}
                  placeholder={t('embedBuilder.footerIconPlaceholder')}
                  onChange={(event) => patch({ footerIconUrl: event.target.value })}
                />
                <div className="flex items-center justify-between rounded-md border border-border px-3 py-2">
                  <Label htmlFor="embed-timestamp">{t('embedBuilder.timestamp')}</Label>
                  <Switch
                    id="embed-timestamp"
                    checked={Boolean(draft.timestamp)}
                    onCheckedChange={(checked) => patch({ timestamp: checked })}
                  />
                </div>
              </div>
              <p className="text-[11px] text-muted-foreground">{t('embedBuilder.mediaHint')}</p>
            </div>
          ) : null}
        </div>

        {showClearHint ? (
          <p className="text-xs text-muted-foreground">{t('embedBuilder.clearHint')}</p>
        ) : null}
        <PlaceholderHelp preset={placeholderPreset} />
        <button
          type="button"
          className="text-xs text-muted-foreground underline-offset-2 hover:underline"
          onClick={() => onChange(null)}
        >
          {t('embedBuilder.clear')}
        </button>
      </div>

      <div className="space-y-2">
        <Label>{t('embedBuilder.preview')}</Label>
        <div className="rounded-md border border-[#1e1f22] bg-[#313338] p-3">
          <div
            className={cn('overflow-hidden rounded-[4px] bg-[#2b2d31]', !hasContent && 'opacity-70')}
            style={{ borderLeft: `4px solid ${colorHex}` }}
          >
            <div className="space-y-2 px-3 py-2">
              {previewAuthor ? (
                <div className="flex items-center gap-2">
                  {authorIcon ? (
                    // eslint-disable-next-line @next/next/no-img-element
                    <img src={authorIcon} alt="" className="size-6 rounded-full object-cover" />
                  ) : null}
                  <p className="text-sm font-medium text-white">{previewAuthor}</p>
                </div>
              ) : null}

              <div className={cn('flex gap-3', thumbnail && 'items-start')}>
                <div className="min-w-0 flex-1 space-y-1">
                  <p
                    className={cn(
                      'text-base font-semibold leading-5',
                      draft.title?.trim() ? 'text-white' : 'text-[#b5bac1]'
                    )}
                  >
                    {previewTitle || '\u00a0'}
                  </p>
                  <p
                    className={cn(
                      'whitespace-pre-wrap text-sm leading-5',
                      draft.description?.trim() ? 'text-[#dbdee1]' : 'text-[#949ba4]'
                    )}
                  >
                    {previewDescription || '\u00a0'}
                  </p>
                </div>
                {thumbnail ? (
                  // eslint-disable-next-line @next/next/no-img-element
                  <img src={thumbnail} alt="" className="size-16 shrink-0 rounded object-cover" />
                ) : null}
              </div>

              {image ? (
                // eslint-disable-next-line @next/next/no-img-element
                <img src={image} alt="" className="mt-1 w-full rounded object-cover" />
              ) : null}

              {previewFooter || draft.timestamp ? (
                <div className="flex items-center gap-2 border-t border-[#3f4147] pt-2">
                  {footerIcon ? (
                    // eslint-disable-next-line @next/next/no-img-element
                    <img src={footerIcon} alt="" className="size-5 rounded-full object-cover" />
                  ) : null}
                  <p className="text-xs text-[#949ba4]">
                    {[previewFooter, draft.timestamp ? t('embedBuilder.timestampPreview') : null]
                      .filter(Boolean)
                      .join(' · ')}
                  </p>
                </div>
              ) : null}
            </div>
          </div>
        </div>
      </div>
    </div>
  );
}
