---
import {
  apiClient,
  resolvePublicApiBaseUrl,
  resolvePublicCommentTurnstileSiteKey,
} from '../lib/api/client';
import { getI18n } from '../lib/i18n';
import type { Comment } from '../lib/api/client';
import type { SiteSettings } from '../lib/types';

interface Props {
  postSlug: string;
  class?: string;
  siteSettings: SiteSettings;
}

const { postSlug, class: className = '', siteSettings } = Astro.props as Props;
const { locale, t } = getI18n(Astro);
const publicApiBaseUrl = resolvePublicApiBaseUrl(Astro.url);
const commentVerificationMode = siteSettings.comments.verificationMode;
const turnstileSiteKey = commentVerificationMode === 'turnstile'
  ? siteSettings.comments.turnstileSiteKey || resolvePublicCommentTurnstileSiteKey()
  : '';

let comments: Comment[] = [];
let error: string | null = null;

try {
  comments = await apiClient.getComments(postSlug, { approved: true, scope: 'article' });
} catch (e) {
  error = e instanceof Error ? e.message : t('comments.loadFailed');
  console.error('Failed to fetch comments:', e);
}

function formatCommentDate(dateStr: string): string {
  const date = new Date(dateStr);
  const now = new Date();
  const diff = now.getTime() - date.getTime();
  const days = Math.floor(diff / (1000 * 60 * 60 * 24));

  if (days === 0) return t('comments.today');
  if (days === 1) return t('comments.yesterday');
  if (days < 7) return t('comments.daysAgo', { count: days });
  if (days < 30) return t('comments.weeksAgo', { count: Math.floor(days / 7) });
  return date.toLocaleDateString(locale, { month: 'short', day: 'numeric' });
}
---

<div
  class={`terminal-comments ${className}`}
  data-post-slug={postSlug}
  data-api-base={publicApiBaseUrl}
  data-verification-mode={commentVerificationMode}
  data-turnstile-site-key={turnstileSiteKey || undefined}
>
  <div class="flex flex-col gap-4 sm:flex-row sm:items-start sm:justify-between">
    <div class="space-y-3">
      <span class="terminal-kicker">
        <i class="fas fa-message"></i>
        {t('comments.kicker')}
      </span>
      <div class="terminal-section-title">
        <span class="terminal-section-icon">
          <i class="fas fa-comments"></i>
        </span>
        <div>
          <h3 class="text-xl font-semibold text-[var(--title-color)]">{t('comments.title')}</h3>
          <p class="text-sm text-[var(--text-secondary)]">
            {t('comments.description', { count: comments.length })}
          </p>
        </div>
      </div>
    </div>

    <button type="button" id="toggle-comment-form" class="terminal-action-button terminal-action-button-primary">
      <i class="fas fa-pen"></i>
      <span>{t('comments.writeComment')}</span>
    </button>
  </div>

  <div id="comment-form-container" class="mt-6 hidden">
    <form id="comment-form" class="terminal-panel-muted space-y-5">
      <div class="grid grid-cols-1 gap-4 md:grid-cols-2">
        <div>
          <label class="terminal-form-label">
            {t('comments.nickname')} <span class="text-[var(--primary)]">*</span>
          </label>
          <input
            type="text"
            name="nickname"
            required
            placeholder={t('comments.nicknamePlaceholder')}
            class="terminal-form-input"
          />
        </div>
        <div>
          <label class="terminal-form-label">
            {t('comments.email')} <span class="text-[var(--text-tertiary)] normal-case tracking-normal">({t('common.optional')})</span>
          </label>
          <input
            type="email"
            name="email"
            placeholder={t('comments.emailPlaceholder')}
            class="terminal-form-input"
          />
        </div>
      </div>

      <div>
        <label class="terminal-form-label">
          {t('comments.message')} <span class="text-[var(--primary)]">*</span>
        </label>
        <textarea
          name="content"
          required
          rows="6"
          maxlength="500"
          placeholder={t('comments.messagePlaceholder')}
          class="terminal-form-textarea resize-y"
        ></textarea>
        <p class="mt-2 text-right text-xs text-[var(--text-tertiary)]">{t('comments.maxChars')}</p>
      </div>

      <div class="hidden" aria-hidden="true">
        <label>
          Website
          <input type="text" name="website" tabindex="-1" autocomplete="off" />
        </label>
      </div>

      {commentVerificationMode !== 'off' && (
        <div class="rounded-2xl border border-[var(--border-color)] bg-[var(--header-bg)]/60 px-4 py-3">
          <div class="flex flex-wrap items-center justify-between gap-2">
            <p class="text-xs font-semibold uppercase tracking-[0.18em] text-[var(--text-tertiary)]">
              {t('common.humanVerification')}
            </p>
            {commentVerificationMode === 'turnstile' ? (
              <span class="text-xs text-[var(--text-tertiary)]">Cloudflare Turnstile</span>
            ) : (
              <button type="button" id="refresh-captcha" class="terminal-action-button px-3 py-2 text-xs">
                <i class="fas fa-rotate-right"></i>
                <span>{t('common.refresh')}</span>
              </button>
            )}
          </div>

          {commentVerificationMode === 'turnstile' ? (
            <>
              <div class="mt-3" data-turnstile-container></div>
              <input type="hidden" name="turnstileToken" />
              <p class="mt-3 text-sm text-[var(--text-secondary)]">{t('common.turnstileHint')}</p>
            </>
          ) : (
            <>
              <p id="captcha-question" class="mt-2 text-sm text-[var(--text-secondary)]">加载中...</p>
              <input type="hidden" name="captchaToken" />
              <input
                type="text"
                name="captchaAnswer"
                required
                inputmode="numeric"
                placeholder="请输入上方答案"
                class="mt-3 terminal-form-input"
              />
            </>
          )}
        </div>
      )}

      <div id="replying-to" class="terminal-panel-muted hidden items-center justify-between gap-3 py-3">
        <span class="text-sm text-[var(--text-secondary)]">
          {t('common.reply')} -> <span id="reply-target" class="font-medium text-[var(--primary)]"></span>
        </span>
        <button type="button" id="cancel-reply" class="terminal-action-button">
          <i class="fas fa-xmark"></i>
          <span>{t('comments.cancelReply')}</span>
        </button>
      </div>

      <div class="flex flex-wrap gap-3">
        <button type="submit" class="terminal-action-button terminal-action-button-primary">
          <i class="fas fa-paper-plane"></i>
          <span>{t('common.submit')}</span>
        </button>
        <button type="button" id="cancel-comment" class="terminal-action-button">
          <i class="fas fa-ban"></i>
          <span>{t('common.close')}</span>
        </button>
      </div>

      <div id="comment-message" class="hidden rounded-2xl border px-4 py-3 text-sm"></div>
    </form>
  </div>

  <div id="comments-list" class="mt-8 space-y-4">
    {error ? (
      <div class="rounded-2xl border px-4 py-4 text-sm text-[var(--danger)]" style="border-color: color-mix(in oklab, var(--danger) 30%, var(--border-color)); background: color-mix(in oklab, var(--danger) 10%, var(--header-bg));">
        {error}
      </div>
    ) : comments.length === 0 ? (
      <div class="terminal-empty">
        <div class="mx-auto flex max-w-md flex-col items-center gap-3">
          <span class="terminal-section-icon">
            <i class="fas fa-comment-slash"></i>
          </span>
          <h4 class="text-lg font-semibold text-[var(--title-color)]">{t('comments.emptyTitle')}</h4>
          <p class="text-sm leading-7 text-[var(--text-secondary)]">
            {t('comments.emptyDescription')}
          </p>
        </div>
      </div>
    ) : (
      comments.map(comment => (
        <div
          class="rounded-2xl border p-4"
          data-comment-id={comment.id}
          style="border-color: color-mix(in oklab, var(--primary) 14%, var(--border-color)); background: linear-gradient(180deg, color-mix(in oklab, var(--terminal-bg) 96%, transparent), color-mix(in oklab, var(--header-bg) 90%, transparent));"
        >
          <div class="flex gap-4">
            <div class="shrink-0">
              <div class="flex h-11 w-11 items-center justify-center rounded-2xl border border-[var(--border-color)] bg-[var(--header-bg)]">
                <i class="fas fa-user text-[var(--primary)]"></i>
              </div>
            </div>

            <div class="min-w-0 flex-1 space-y-3">
              <div class="flex flex-wrap items-center gap-2">
                <span class="font-semibold text-[var(--title-color)]">{comment.author || t('comments.anonymous')}</span>
                <span class="terminal-chip px-2.5 py-1 text-xs">
                  <i class="far fa-clock text-[var(--primary)]"></i>
                  {formatCommentDate(comment.created_at)}
                </span>
              </div>

              <p class="text-sm leading-7 text-[var(--text-secondary)]">{comment.content}</p>

              <div class="flex flex-wrap gap-2 text-xs">
                <button
                  type="button"
                  class="reply-btn terminal-action-button px-3 py-2 text-xs"
                  data-author={comment.author}
                  data-id={comment.id}
                >
                  <i class="fas fa-reply"></i>
                  <span>{t('common.reply')}</span>
                </button>
                <button
                  type="button"
                  class="like-btn terminal-action-button px-3 py-2 text-xs"
                >
                  <i class="far fa-thumbs-up"></i>
                  <span>{t('common.like')}</span>
                </button>
              </div>
            </div>
          </div>
        </div>
      ))
    )}
  </div>
</div>

<script>
  import { mountTurnstile, type MountedTurnstile } from '../lib/utils/turnstile';

  const t = window.__termiTranslate;
  const wrapper = document.querySelector('.terminal-comments');
  const toggleBtn = document.getElementById('toggle-comment-form');
  const formContainer = document.getElementById('comment-form-container');
  const cancelBtn = document.getElementById('cancel-comment');
  const form = document.getElementById('comment-form') as HTMLFormElement | null;
  const replyingTo = document.getElementById('replying-to');
  const replyTarget = document.getElementById('reply-target');
  const cancelReply = document.getElementById('cancel-reply');
  const replyBtns = document.querySelectorAll('.reply-btn');
  const messageBox = document.getElementById('comment-message');
  const captchaQuestion = document.getElementById('captcha-question');
  const refreshCaptchaBtn = document.getElementById('refresh-captcha');
  const postSlug = wrapper?.getAttribute('data-post-slug') || '';
  const apiBase = wrapper?.getAttribute('data-api-base') || '/api';
  const verificationMode = wrapper?.getAttribute('data-verification-mode') || 'captcha';
  const useTurnstile = verificationMode === 'turnstile';
  const useCaptcha = verificationMode === 'captcha';
  const turnstileSiteKey = wrapper?.getAttribute('data-turnstile-site-key') || '';
  const turnstileContainer = form?.querySelector('[data-turnstile-container]') as HTMLElement | null;
  const turnstileTokenInput = form?.querySelector('input[name="turnstileToken"]') as HTMLInputElement | null;
  const captchaTokenInput = form?.querySelector('input[name="captchaToken"]') as HTMLInputElement | null;
  const captchaAnswerInput = form?.querySelector('input[name="captchaAnswer"]') as HTMLInputElement | null;
  let turnstileWidget: MountedTurnstile | null = null;

  function showMessage(message: string, type: 'success' | 'error' | 'info') {
    if (!messageBox) return;

    messageBox.classList.remove(
      'hidden',
      'text-[var(--success)]',
      'text-[var(--danger)]',
      'text-[var(--primary)]'
    );

    if (type === 'success') {
      messageBox.classList.add('text-[var(--success)]');
      messageBox.setAttribute(
        'style',
        'border-color: color-mix(in oklab, var(--success) 28%, var(--border-color)); background: color-mix(in oklab, var(--success) 10%, var(--header-bg));'
      );
    } else if (type === 'error') {
      messageBox.classList.add('text-[var(--danger)]');
      messageBox.setAttribute(
        'style',
        'border-color: color-mix(in oklab, var(--danger) 28%, var(--border-color)); background: color-mix(in oklab, var(--danger) 10%, var(--header-bg));'
      );
    } else {
      messageBox.classList.add('text-[var(--primary)]');
      messageBox.setAttribute(
        'style',
        'border-color: color-mix(in oklab, var(--primary) 28%, var(--border-color)); background: color-mix(in oklab, var(--primary) 10%, var(--header-bg));'
      );
    }

    messageBox.textContent = message;
    messageBox.classList.remove('hidden');
  }

  function resetReply() {
    replyingTo?.classList.add('hidden');
    replyingTo?.removeAttribute('data-reply-to');
  }

  async function loadCaptcha(showError = true) {
    if (!captchaQuestion || !captchaTokenInput) {
      return;
    }

    captchaQuestion.textContent = '加载中...';
    captchaTokenInput.value = '';
    if (captchaAnswerInput) {
      captchaAnswerInput.value = '';
    }

    try {
      const response = await fetch(`${apiBase}/comments/captcha`);
      if (!response.ok) {
        throw new Error(await response.text());
      }

      const payload = await response.json() as { token?: string; question?: string };
      captchaTokenInput.value = payload.token || '';
      captchaQuestion.textContent = payload.question || '请刷新验证码';
    } catch (error) {
      captchaQuestion.textContent = '验证码加载失败，请刷新重试';
      if (showError) {
        showMessage(
          t('comments.submitFailed', { message: error instanceof Error ? error.message : t('common.unknownError') }),
          'error'
        );
      }
    }
  }

  async function ensureTurnstile(showError = true) {
    if (!turnstileSiteKey || !turnstileContainer || !turnstileTokenInput) {
      return;
    }

    turnstileTokenInput.value = '';

    if (turnstileWidget) {
      turnstileWidget.reset();
      return;
    }

    try {
      turnstileWidget = await mountTurnstile(turnstileContainer, {
        siteKey: turnstileSiteKey,
        onToken(token) {
          turnstileTokenInput.value = token;
        },
        onExpire() {
          turnstileTokenInput.value = '';
        },
        onError() {
          turnstileTokenInput.value = '';
          if (showError) {
            showMessage(t('common.turnstileLoadFailed'), 'error');
          }
        },
      });
    } catch (error) {
      if (showError) {
        showMessage(
          error instanceof Error ? error.message : t('common.turnstileLoadFailed'),
          'error',
        );
      }
    }
  }

  function resetHumanCheck() {
    if (useTurnstile) {
      turnstileTokenInput && (turnstileTokenInput.value = '');
      turnstileWidget?.reset();
      return;
    }

    if (useCaptcha) {
      void loadCaptcha(false);
    }
  }

  toggleBtn?.addEventListener('click', () => {
    formContainer?.classList.toggle('hidden');
    if (!formContainer?.classList.contains('hidden')) {
      form?.querySelector('textarea')?.focus();
    }
  });

  cancelBtn?.addEventListener('click', () => {
    formContainer?.classList.add('hidden');
    resetReply();
  });

  replyBtns.forEach(btn => {
    btn.addEventListener('click', () => {
      const author = btn.getAttribute('data-author');
      const commentId = btn.getAttribute('data-id');

      if (replyingTo && replyTarget) {
        replyingTo.classList.remove('hidden');
        replyingTo.classList.add('flex');
        replyTarget.textContent = author || t('comments.anonymous');
        replyingTo.setAttribute('data-reply-to', commentId || '');
      }

      formContainer?.classList.remove('hidden');
      form?.querySelector('textarea')?.focus();
    });
  });

  cancelReply?.addEventListener('click', () => {
    replyingTo?.classList.remove('flex');
    resetReply();
  });

  refreshCaptchaBtn?.addEventListener('click', () => {
    void loadCaptcha(false);
  });

  form?.addEventListener('submit', async (e) => {
    e.preventDefault();

    const formData = new FormData(form);
    const replyToId = replyingTo?.getAttribute('data-reply-to');

    if (useTurnstile) {
      const token = String(formData.get('turnstileToken') || '').trim();
      if (!token) {
        showMessage(t('common.turnstileRequired'), 'error');
        return;
      }
    }

    try {
      showMessage(t('comments.submitting'), 'info');

      const response = await fetch(`${apiBase}/comments`, {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
        },
        body: JSON.stringify({
          postSlug,
          nickname: formData.get('nickname'),
          email: formData.get('email'),
          content: formData.get('content'),
          scope: 'article',
          replyToCommentId: replyToId ? Number(replyToId) : null,
          turnstileToken: formData.get('turnstileToken'),
          captchaToken: formData.get('captchaToken'),
          captchaAnswer: formData.get('captchaAnswer'),
          website: formData.get('website'),
        }),
      });

      if (!response.ok) {
        throw new Error(await response.text());
      }

      form.reset();
      replyingTo?.classList.remove('flex');
      resetReply();
      formContainer?.classList.add('hidden');
      showMessage(t('comments.submitSuccess'), 'success');
      resetHumanCheck();
    } catch (error) {
      showMessage(t('comments.submitFailed', { message: error instanceof Error ? error.message : t('common.unknownError') }), 'error');
      resetHumanCheck();
    }
  });

  document.querySelectorAll('.like-btn').forEach(btn => {
    btn.addEventListener('click', () => {
      const icon = btn.querySelector('i');
      if (icon?.classList.contains('far')) {
        icon.classList.replace('far', 'fas');
        btn.classList.add('terminal-action-button-primary');
      } else if (icon?.classList.contains('fas')) {
        icon.classList.replace('fas', 'far');
        btn.classList.remove('terminal-action-button-primary');
      }
    });
  });

  if (useTurnstile) {
    void ensureTurnstile(false);
  } else if (useCaptcha) {
    void loadCaptcha(false);
  }

  wrapper?.setAttribute('data-comments-ready', 'true');
  window.__termiCommentsReady = true;
</script>
