'use client';

import {
  componentsV2HasContent,
  embedHasContent,
  type MessageComponentsV2,
  type ScheduledMessageDashboard,
  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 { DiscordChannelSelect } from '@/components/ui/discord-channel-select';
import {
  DiscordComponentsV2Builder,
  emptyComponentsV2,
  normalizeComponentsV2
} from '@/components/ui/discord-components-v2-builder';
import { DiscordEmbedBuilder, normalizeEmbed } from '@/components/ui/discord-embed-builder';
import { DiscordRoleSelect } 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 { Textarea } from '@/components/ui/textarea';
import { cn } from '@/lib/utils';

type ScheduleContentMode = 'text' | 'embed' | 'components_v2';
type ScheduleTimingMode = 'once' | 'cron';

const EMPTY_DRAFT = {
  channelId: '',
  contentMode: 'text' as ScheduleContentMode,
  timingMode: 'once' as ScheduleTimingMode,
  content: '',
  embed: null as WelcomeEmbed | null,
  components: null as MessageComponentsV2 | null,
  rolePingId: '',
  cron: '',
  runAt: ''
};

function formatTiming(schedule: ScheduledMessageDashboard, t: (key: string) => string): string {
  if (schedule.cron) {
    return `${t('modulePages.scheduler.cron')}: ${schedule.cron}`;
  }
  if (schedule.runAt) {
    return `${new Date(schedule.runAt).toLocaleString(undefined, {
      dateStyle: 'medium',
      timeStyle: 'short'
    })}`;
  }
  return '—';
}

function schedulePreview(schedule: ScheduledMessageDashboard, t: (key: string) => string): string {
  if (schedule.content?.trim()) {
    return schedule.content;
  }
  if (componentsV2HasContent(schedule.components)) {
    return t('modulePages.scheduler.componentsPreview');
  }
  if (schedule.embed?.title?.trim()) {
    return schedule.embed.title;
  }
  if (schedule.embed?.description?.trim()) {
    return schedule.embed.description;
  }
  if (schedule.embed?.authorName?.trim()) {
    return schedule.embed.authorName;
  }
  if (schedule.embed?.footerText?.trim()) {
    return schedule.embed.footerText;
  }
  return t('modulePages.scheduler.noContent');
}

function scheduleErrorMessage(code: string | undefined, t: (key: string) => string): string {
  if (code === 'invalid_cron') {
    return t('modulePages.scheduler.errors.invalidCron');
  }
  if (code === 'invalid_when') {
    return t('modulePages.scheduler.errors.invalidWhen');
  }
  if (code === 'missing_schedule_time') {
    return t('modulePages.scheduler.errors.missingScheduleTime');
  }
  return code?.trim() ? code : t('common.saveError');
}

interface SchedulerManagerProps {
  guildId: string;
  initialSchedules: ScheduledMessageDashboard[];
}

export function SchedulerManager({ guildId, initialSchedules }: SchedulerManagerProps) {
  const t = useTranslations();
  const [schedules, setSchedules] = useState<ScheduledMessageDashboard[]>(initialSchedules);
  const [draft, setDraft] = useState(EMPTY_DRAFT);
  const [creating, setCreating] = useState(false);

  async function handleCreate() {
    const embed = draft.contentMode === 'embed' ? normalizeEmbed(draft.embed) : null;
    const components =
      draft.contentMode === 'components_v2' ? normalizeComponentsV2(draft.components ?? emptyComponentsV2()) : null;
    const content = draft.contentMode === 'text' ? draft.content.trim() || null : null;

    const hasContent =
      Boolean(content) ||
      (draft.contentMode === 'embed' && (embedHasContent(embed) || embed?.color !== undefined)) ||
      (draft.contentMode === 'components_v2' && componentsV2HasContent(components));

    const cron = draft.timingMode === 'cron' ? draft.cron.trim() : '';
    const runAt = draft.timingMode === 'once' ? draft.runAt.trim() : '';

    if (!draft.channelId.trim() || !hasContent || (!cron && !runAt)) {
      toast.error(t('modulePages.scheduler.formIncomplete'));
      return;
    }

    setCreating(true);
    try {
      const response = await fetch(`/api/guilds/${guildId}/scheduler`, {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({
          channelId: draft.channelId.trim(),
          content,
          embed,
          components,
          rolePingId: draft.rolePingId.trim() || undefined,
          // Send naive datetime-local; server interprets it in the guild timezone.
          cron: cron || null,
          runAt: cron ? null : runAt || null
        })
      });
      const body = (await response.json().catch(() => null)) as
        | (ScheduledMessageDashboard & { error?: string })
        | null;
      if (!response.ok || !body) {
        toast.error(scheduleErrorMessage(body?.error, t));
        return;
      }
      setSchedules((prev) => [...prev, body]);
      setDraft(EMPTY_DRAFT);
      toast.success(t('modulePages.scheduler.created'));
    } catch {
      toast.error(t('common.saveError'));
    } finally {
      setCreating(false);
    }
  }

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

  return (
    <div className="space-y-6">
      <FieldAnchor id="field-scheduler-create">
      <Card>
        <CardHeader>
          <CardTitle>{t('modulePages.scheduler.createTitle')}</CardTitle>
          <CardDescription>{t('modulePages.scheduler.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.scheduler.channelId')}</Label>
              <DiscordChannelSelect
                guildId={guildId}
                value={draft.channelId}
                onChange={(channelId) => setDraft((prev) => ({ ...prev, channelId }))}
              />
            </div>
            <div className="space-y-2">
              <Label>{t('modulePages.scheduler.rolePingId')}</Label>
              <DiscordRoleSelect
                guildId={guildId}
                value={draft.rolePingId}
                onChange={(rolePingId) => setDraft((prev) => ({ ...prev, rolePingId }))}
                placeholder={t('common.optional')}
              />
            </div>
          </div>

          <div className="space-y-2">
            <Label>{t('modulePages.scheduler.timingMode')}</Label>
            <div className="flex flex-wrap gap-2">
              {(['once', 'cron'] as ScheduleTimingMode[]).map((mode) => (
                <Button
                  key={mode}
                  type="button"
                  variant={draft.timingMode === mode ? 'default' : 'outline'}
                  size="sm"
                  className={cn(draft.timingMode !== mode && 'text-muted-foreground')}
                  onClick={() =>
                    setDraft((prev) => ({
                      ...prev,
                      timingMode: mode,
                      cron: mode === 'cron' ? prev.cron : '',
                      runAt: mode === 'once' ? prev.runAt : ''
                    }))
                  }
                >
                  {t(`modulePages.scheduler.timingModes.${mode}`)}
                </Button>
              ))}
            </div>
          </div>

          {draft.timingMode === 'cron' ? (
            <div className="space-y-2">
              <Label htmlFor="scheduler-cron">{t('modulePages.scheduler.cron')}</Label>
              <Input
                id="scheduler-cron"
                value={draft.cron}
                onChange={(event) => setDraft((prev) => ({ ...prev, cron: event.target.value }))}
                placeholder="0 9 * * *"
                autoComplete="off"
              />
            </div>
          ) : (
            <div className="space-y-2">
              <Label htmlFor="scheduler-run-at">{t('modulePages.scheduler.runAt')}</Label>
              <Input
                id="scheduler-run-at"
                type="datetime-local"
                value={draft.runAt}
                onChange={(event) => setDraft((prev) => ({ ...prev, runAt: event.target.value }))}
              />
            </div>
          )}

          <div className="space-y-2">
            <Label>{t('modulePages.scheduler.contentMode')}</Label>
            <div className="flex flex-wrap gap-2">
              {(['text', 'embed', 'components_v2'] as ScheduleContentMode[]).map((mode) => (
                <Button
                  key={mode}
                  type="button"
                  variant={draft.contentMode === mode ? 'default' : 'outline'}
                  size="sm"
                  className={cn(draft.contentMode !== mode && 'text-muted-foreground')}
                  onClick={() => setDraft((prev) => ({ ...prev, contentMode: mode }))}
                >
                  {t(`modulePages.scheduler.contentModes.${mode}`)}
                </Button>
              ))}
            </div>
          </div>

          {draft.contentMode === 'text' ? (
            <div className="space-y-2">
              <Label>{t('modulePages.scheduler.content')}</Label>
              <Textarea
                value={draft.content}
                onChange={(event) => setDraft((prev) => ({ ...prev, content: event.target.value }))}
                rows={3}
              />
              <PlaceholderHelp preset="scheduler" />
            </div>
          ) : null}

          {draft.contentMode === 'embed' ? (
            <div className="space-y-2">
              <Label>{t('modulePages.scheduler.embed')}</Label>
              <DiscordEmbedBuilder
                value={draft.embed}
                onChange={(embed) => setDraft((prev) => ({ ...prev, embed }))}
                placeholderPreset="scheduler"
              />
            </div>
          ) : null}

          {draft.contentMode === 'components_v2' ? (
            <div className="space-y-2">
              <Label>{t('modulePages.scheduler.components')}</Label>
              <DiscordComponentsV2Builder
                guildId={guildId}
                value={draft.components ?? emptyComponentsV2()}
                onChange={(components) => setDraft((prev) => ({ ...prev, components }))}
                placeholderPreset="scheduler"
              />
            </div>
          ) : null}

          <p className="text-xs text-muted-foreground">{t('modulePages.scheduler.cronHint')}</p>
          <Button type="button" onClick={handleCreate} disabled={creating}>
            <Plus className="size-4" />
            {creating ? t('common.saving') : t('modulePages.scheduler.create')}
          </Button>
        </CardContent>
      </Card>
      </FieldAnchor>

      <Card>
        <CardHeader>
          <CardTitle>{t('modulePages.scheduler.listTitle')}</CardTitle>
          <CardDescription>{t('modulePages.scheduler.listDescription')}</CardDescription>
        </CardHeader>
        <CardContent className="space-y-3">
          {schedules.length === 0 && (
            <p className="text-sm text-muted-foreground">{t('modulePages.scheduler.empty')}</p>
          )}
          {schedules.map((schedule) => (
            <div key={schedule.id} className="flex flex-wrap items-start justify-between gap-3 rounded-md border border-border p-4">
              <div>
                <p className="font-medium">{schedulePreview(schedule, t)}</p>
                <p className="text-xs text-muted-foreground">
                  #{schedule.channelId} · {formatTiming(schedule, t)}
                  {schedule.rolePingId ? ` · @${schedule.rolePingId}` : ''}
                </p>
              </div>
              <Button type="button" variant="ghost" size="icon" aria-label={t('common.remove')} onClick={() => handleDelete(schedule)}>
                <Trash2 className="size-4" />
              </Button>
            </div>
          ))}
        </CardContent>
      </Card>
    </div>
  );
}
