'use client';

import { useCallback, useEffect, useState } from 'react';
import { motion } from 'framer-motion';
import {
  Bitcoin,
  CheckCircle2,
  Copy,
  Globe,
  Link as LinkIcon,
  Zap,
} from 'lucide-react';
import { Activity } from '@/app/admin/_components/icons';
import { CustomDropdown } from '@/app/admin/_components/CustomDropdown';
import { CustomToggle } from '@/app/admin/_components/CustomToggle';
import { getResponseErrorTextWithRequestId } from '@/lib/api-client';
import {
  buildPlanPricesPayload,
  cn,
  formatDateTime,
  toCryptobotDraft,
} from '@/lib/admin/utils';
import {
  NETWORK_LABEL_BY_VALUE,
  NETWORK_OPTIONS,
  NETWORK_VALUE_BY_LABEL,
  type CryptobotDraft,
  type CryptobotSettingsResponse,
  type PaidPlanPrices,
} from '@/lib/types/admin';
import { cryptobotSettingsCache } from './_cache';

type CryptobotTabProps = {
  isAdmin: boolean;
  setErrorMessage: (message: string) => void;
  setSuccessMessage: (message: string) => void;
};

export function CryptobotTab({ isAdmin, setErrorMessage, setSuccessMessage }: CryptobotTabProps) {
  const initialCached = cryptobotSettingsCache.read()?.data ?? null;
  const [cryptoSettings, setCryptoSettings] = useState<CryptobotSettingsResponse | null>(initialCached);
  const [cryptoDraft, setCryptoDraft] = useState<CryptobotDraft | null>(
    initialCached ? toCryptobotDraft(initialCached) : null
  );
  const [cryptoApiToken, setCryptoApiToken] = useState('');
  const [isCryptoSaving, setIsCryptoSaving] = useState(false);
  const [isCryptoTesting, setIsCryptoTesting] = useState(false);

  const getApiErrorText = useCallback(async (response: Response, fallback: string) => {
    return getResponseErrorTextWithRequestId(response, fallback);
  }, []);

  const fetchCryptobotSettings = useCallback(async (options?: { force?: boolean }) => {
    if (!isAdmin) return;

    const data = await cryptobotSettingsCache.fetch(async () => {
      const response = await fetch('/api/admin/billing/providers/cryptobot', { cache: 'no-store' });
      if (!response.ok) {
        throw new Error(await getApiErrorText(response, 'Не удалось загрузить настройки CryptoBot'));
      }
      return await response.json() as CryptobotSettingsResponse;
    }, options);

    setCryptoSettings(data);
    setCryptoDraft(toCryptobotDraft(data));
  }, [getApiErrorText, isAdmin]);

  useEffect(() => {
    if (!isAdmin) return;
    const cached = cryptobotSettingsCache.read();
    if (cached && cryptobotSettingsCache.isFresh(cached)) {
      // Fresh cache hit — state is already populated from initialCached.
      return;
    }
    let cancelled = false;
    void fetchCryptobotSettings().catch((error) => {
      if (!cancelled) {
        setErrorMessage(error instanceof Error ? error.message : 'Не удалось загрузить настройки CryptoBot');
      }
    });
    return () => {
      cancelled = true;
    };
  }, [fetchCryptobotSettings, isAdmin, setErrorMessage]);

  const handleSaveCrypto = useCallback(async () => {
    if (!isAdmin || !cryptoDraft) return;

    const invoiceExpiresInSec = Number.parseInt(cryptoDraft.invoiceExpiresInSec, 10);
    if (!Number.isInteger(invoiceExpiresInSec) || invoiceExpiresInSec <= 0) {
      setErrorMessage('Срок жизни счёта должен быть целым числом больше 0.');
      return;
    }

    let planPricesPayload: PaidPlanPrices;
    try {
      planPricesPayload = buildPlanPricesPayload(cryptoDraft.planPrices);
    } catch (error) {
      setErrorMessage(error instanceof Error ? error.message : 'Некорректные цены тарифов.');
      return;
    }

    setIsCryptoSaving(true);
    setSuccessMessage('');

    try {
      const payload: Record<string, unknown> = {
        enabled: cryptoDraft.enabled,
        acceptedAssets: cryptoDraft.acceptedAssets.trim() ? cryptoDraft.acceptedAssets.trim() : null,
        invoiceExpiresInSec,
        allowComments: cryptoDraft.allowComments,
        allowAnonymous: cryptoDraft.allowAnonymous,
        network: cryptoDraft.network,
        planPrices: planPricesPayload,
      };

      if (cryptoApiToken.trim()) {
        payload.apiToken = cryptoApiToken.trim();
      }

      const response = await fetch('/api/admin/billing/providers/cryptobot', {
        method: 'PATCH',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify(payload),
      });
      if (!response.ok) {
        throw new Error(await getApiErrorText(response, 'Не удалось сохранить настройки CryptoBot'));
      }

      const data = await response.json() as CryptobotSettingsResponse;
      cryptobotSettingsCache.set(data);
      setCryptoSettings(data);
      setCryptoDraft(toCryptobotDraft(data));
      setCryptoApiToken('');
      setErrorMessage('');
      setSuccessMessage('Настройки CryptoBot сохранены.');
    } catch (error) {
      setErrorMessage(error instanceof Error ? error.message : 'Не удалось сохранить настройки CryptoBot');
    } finally {
      setIsCryptoSaving(false);
    }
  }, [cryptoApiToken, cryptoDraft, getApiErrorText, isAdmin, setErrorMessage, setSuccessMessage]);

  const handleTestCrypto = useCallback(async () => {
    if (!isAdmin) return;

    setIsCryptoTesting(true);
    setSuccessMessage('');

    try {
      const response = await fetch('/api/admin/billing/providers/cryptobot/test', {
        method: 'POST',
      });
      if (!response.ok) {
        throw new Error(await getApiErrorText(response, 'Не удалось проверить подключение CryptoBot'));
      }

      await fetchCryptobotSettings({ force: true });
      setErrorMessage('');
      setSuccessMessage('Подключение CryptoBot успешно проверено.');
    } catch (error) {
      setErrorMessage(error instanceof Error ? error.message : 'Не удалось проверить подключение CryptoBot');
    } finally {
      setIsCryptoTesting(false);
    }
  }, [fetchCryptobotSettings, getApiErrorText, isAdmin, setErrorMessage, setSuccessMessage]);

  const handleCopyWebhook = useCallback(async () => {
    if (!cryptoSettings?.webhookUrl) return;
    try {
      await navigator.clipboard.writeText(cryptoSettings.webhookUrl);
      setErrorMessage('');
      setSuccessMessage('Адрес уведомлений CryptoBot скопирован.');
    } catch {
      setErrorMessage('Не удалось скопировать адрес уведомлений.');
    }
  }, [cryptoSettings?.webhookUrl, setErrorMessage, setSuccessMessage]);

  const canTestCrypto = Boolean(cryptoSettings?.hasToken);

  return (
    <motion.div key="cryptobot" initial={{ opacity: 0, y: 10 }} animate={{ opacity: 1, y: 0 }} exit={{ opacity: 0, y: -10 }} className="space-y-6 max-w-5xl mx-auto pb-10">
      {!isAdmin ? (
        <div className="rounded-2xl border border-white/10 bg-white/[0.02] p-6 text-sm text-gray-300">
          Настройки CryptoBot доступны только администратору.
        </div>
      ) : !cryptoDraft || !cryptoSettings ? (
        <div className="rounded-2xl border border-white/10 bg-white/[0.02] p-10 text-sm text-gray-400 text-center">
          <div className="inline-block w-6 h-6 border-2 border-violet-500 border-t-transparent rounded-full animate-spin mb-3" />
          <p>Загрузка настроек CryptoBot...</p>
        </div>
      ) : (
        <>
          <div className="flex flex-col md:flex-row md:items-center justify-between gap-6 mb-8 group">
            <div>
              <h2 className="text-2xl font-bold flex items-center gap-3">
                <div className="p-2.5 bg-yellow-500/10 rounded-xl border border-yellow-500/20 group-hover:scale-110 transition-transform">
                  <Bitcoin className="w-6 h-6 text-yellow-500 drop-shadow-[0_0_10px_rgba(234,179,8,0.3)]" />
                </div>
                Платёжная интеграция CryptoBot
              </h2>
              <p className="text-gray-400 mt-2 max-w-2xl leading-relaxed text-sm">
                Управление подключением к API @CryptoBot для автоматического приема платежей и выдачи подписок.
              </p>
            </div>
            <div className="flex items-center gap-3 shrink-0">
              <button
                type="button"
                onClick={() => void handleSaveCrypto()}
                disabled={isCryptoSaving}
                className="bg-[#2AABEE] hover:bg-[#229ED9] text-white font-medium px-6 py-2.5 rounded-xl text-sm transition-all shadow-[0_0_20px_rgba(42,171,238,0.2)] hover:shadow-[0_0_25px_rgba(42,171,238,0.4)] hover:-translate-y-0.5 disabled:opacity-60"
              >
                {isCryptoSaving ? 'Сохранение...' : 'Сохранить все'}
              </button>
            </div>
          </div>

          <div className="grid grid-cols-1 lg:grid-cols-2 gap-6 items-start">
            <div className="space-y-6 flex flex-col min-w-0">
              <div className="bg-[#0A0A0A] border border-white/5 rounded-3xl p-6 md:p-8 shadow-xl hover:border-white/10 transition-colors">
                <h3 className="text-lg font-bold text-white mb-6 flex items-center gap-2">
                  <Zap className="w-5 h-5 text-gray-400" /> Основные настройки
                </h3>

                <div className="space-y-5">
                  <div className="flex items-center justify-between gap-4 bg-white/[0.02] border border-white/[0.05] hover:border-violet-500/30 p-4 rounded-2xl transition-all group/toggle">
                    <div className="space-y-1 pr-4 min-w-0">
                      <span className="text-sm font-bold text-white block group-hover/toggle:text-violet-200 transition-colors">Приём платежей CryptoBot</span>
                      <span className="text-xs text-gray-500 block">Кнопка оплаты будет показана на странице тарифов</span>
                    </div>
                    <CustomToggle checked={cryptoDraft.enabled} onChange={(value) => setCryptoDraft((prev) => (prev ? { ...prev, enabled: value } : prev))} />
                  </div>

                  <div className="space-y-2">
                    <label className="text-sm text-gray-300 font-medium ml-1">Сеть приложения</label>
                    <CustomDropdown
                      value={NETWORK_LABEL_BY_VALUE[cryptoDraft.network]}
                      onChange={(value) => {
                        const network = NETWORK_VALUE_BY_LABEL[value];
                        if (!network) return;
                        setCryptoDraft((prev) => (prev ? { ...prev, network } : prev));
                      }}
                      options={NETWORK_OPTIONS}
                    />
                  </div>

                  <div className="space-y-2">
                    <label className="text-sm text-gray-300 font-medium ml-1">Срок жизни счёта, сек</label>
                    <input
                      type="number"
                      min={1}
                      value={cryptoDraft.invoiceExpiresInSec}
                      onChange={(event) => setCryptoDraft((prev) => (prev ? { ...prev, invoiceExpiresInSec: event.target.value } : prev))}
                      className="w-full bg-black/40 border border-white/10 rounded-xl px-3 py-2.5 text-sm outline-none focus:border-violet-500/50 text-white"
                    />
                  </div>

                  <div className="grid grid-cols-1 sm:grid-cols-2 gap-3">
                    <div className="flex items-center justify-between gap-3 rounded-xl border border-white/10 bg-white/[0.02] px-3 py-2.5 min-w-0">
                      <span className="text-sm text-gray-300 truncate">Комментарии</span>
                      <CustomToggle checked={cryptoDraft.allowComments} onChange={(value) => setCryptoDraft((prev) => (prev ? { ...prev, allowComments: value } : prev))} />
                    </div>
                    <div className="flex items-center justify-between gap-3 rounded-xl border border-white/10 bg-white/[0.02] px-3 py-2.5 min-w-0">
                      <span className="text-sm text-gray-300 truncate">Анонимные оплаты</span>
                      <CustomToggle checked={cryptoDraft.allowAnonymous} onChange={(value) => setCryptoDraft((prev) => (prev ? { ...prev, allowAnonymous: value } : prev))} />
                    </div>
                  </div>
                </div>
              </div>

              <div className="bg-[#0A0A0A] border border-white/5 rounded-3xl p-6 md:p-8 shadow-xl hover:border-white/10 transition-colors">
                <h3 className="text-lg font-bold text-white mb-6 flex items-center gap-2">
                  <LinkIcon className="w-5 h-5 text-gray-400" /> Подключение и API
                </h3>

                <div className="space-y-5">
                  <div className="space-y-2">
                    <label className="text-sm text-gray-300 font-medium ml-1 flex justify-between items-center gap-2">
                      <span>API токен приложения</span>
                      <span className={cn(
                        'text-[10px] px-2 py-1 rounded-lg border font-bold uppercase tracking-wider flex items-center gap-1',
                        cryptoSettings.hasToken
                          ? 'text-green-400 bg-green-500/10 border-green-500/20'
                          : 'text-gray-400 bg-white/5 border-white/10'
                      )}>
                        <CheckCircle2 className="w-3 h-3" /> {cryptoSettings.hasToken ? 'Сохранён' : 'Не задан'}
                      </span>
                    </label>
                    <div className="flex gap-2">
                      <input
                        type="password"
                        placeholder={cryptoSettings.hasToken ? 'Оставьте пустым, чтобы не менять' : 'Введите API токен'}
                        value={cryptoApiToken}
                        onChange={(event) => setCryptoApiToken(event.target.value)}
                        className="flex-1 min-w-0 bg-black/40 hover:bg-white/[0.02] border border-white/10 rounded-2xl px-4 py-2.5 text-sm outline-none focus:border-violet-500/50 focus:bg-white/[0.02] placeholder-gray-600 transition-all text-white"
                      />
                      <button
                        type="button"
                        onClick={() => void handleTestCrypto()}
                        disabled={isCryptoTesting || !canTestCrypto}
                        className="px-4 py-2.5 bg-white/5 hover:bg-white/10 border border-white/10 rounded-2xl text-sm font-medium transition-colors text-white whitespace-nowrap disabled:opacity-60"
                      >
                        {isCryptoTesting ? 'Проверка...' : 'Проверить'}
                      </button>
                    </div>
                    {!canTestCrypto ? (
                      <p className="text-[11px] text-gray-500 ml-1">Сначала сохраните ключи и идентификаторы, затем можно выполнить проверку.</p>
                    ) : null}
                    <p className="text-[11px] text-gray-500 ml-1">Получите токен в настройках вашего приложения внутри бота.</p>
                  </div>

                  <div className="space-y-2">
                    <label className="text-sm text-gray-300 font-medium ml-1">Принимаемые активы</label>
                    <input
                      type="text"
                      placeholder="TON, USDT, BTC"
                      value={cryptoDraft.acceptedAssets}
                      onChange={(event) => setCryptoDraft((prev) => (prev ? { ...prev, acceptedAssets: event.target.value } : prev))}
                      className="w-full bg-black/40 hover:bg-white/[0.02] border border-white/10 rounded-2xl px-4 py-2.5 text-sm outline-none focus:border-violet-500/50 focus:bg-white/[0.02] placeholder-gray-600 font-mono transition-all text-white"
                    />
                    <p className="text-[11px] text-gray-500 ml-1">Через запятую или пусто — принимать все доступные.</p>
                  </div>

                  <div className="space-y-2">
                    <label className="text-sm text-gray-300 font-medium ml-1 flex items-center gap-2">
                      <Globe className="w-4 h-4 text-violet-400" /> Адрес уведомлений об оплате
                    </label>
                    <div className="flex gap-2 relative">
                      <input type="text" readOnly value={cryptoSettings.webhookUrl} className="flex-1 min-w-0 bg-black/40 border border-white/10 rounded-2xl px-4 py-2.5 pr-11 text-xs outline-none text-violet-200 font-mono" />
                      <button type="button" onClick={() => void handleCopyWebhook()} className="absolute right-1.5 top-1/2 -translate-y-1/2 p-2 bg-white/5 hover:bg-white/10 rounded-xl text-gray-400 hover:text-white transition-colors border border-white/5 hover:border-white/10" title="Скопировать адрес">
                        <Copy className="w-3.5 h-3.5" />
                      </button>
                    </div>
                    <p className="text-[11px] text-gray-500 ml-1">Скопируйте этот адрес и вставьте его в настройках приложения @CryptoBot — на него будут приходить уведомления об оплате.</p>
                  </div>
                </div>
              </div>
            </div>

            <div className="min-w-0">
              <div className="bg-white/[0.02] border border-white/5 rounded-3xl p-6 md:p-8 shadow-xl lg:sticky lg:top-4">
                <h3 className="font-bold text-lg text-white flex items-center gap-3 mb-6">
                  <div className="p-2 bg-green-500/20 rounded-xl border border-green-500/30 text-green-400">
                    <Activity className="w-4 h-4" />
                  </div>
                  Диагностика связи
                </h3>

                <div className="space-y-5 text-sm">
                  <div className="flex flex-col gap-1.5 border-b border-white/5 pb-5">
                    <span className="text-gray-500 text-xs font-bold uppercase tracking-wider">Приложение в CryptoBot</span>
                    <span className="text-gray-200 font-medium text-base">{cryptoSettings.diagnostics.appName || '—'}</span>
                    <span className="text-gray-500 text-xs font-mono">
                      {cryptoSettings.diagnostics.appUsername ? `@${cryptoSettings.diagnostics.appUsername}` : '—'}
                      {cryptoSettings.diagnostics.appId ? ` · ID: ${cryptoSettings.diagnostics.appId}` : ''}
                    </span>
                  </div>

                  <div className="grid grid-cols-1 sm:grid-cols-2 gap-4 border-b border-white/5 pb-5">
                    <div className="flex flex-col gap-1.5">
                      <span className="text-gray-500 text-xs font-bold uppercase tracking-wider">API Токен</span>
                      <span className={cn(
                        'font-medium flex items-center gap-2 w-max px-3 py-1 rounded-lg border',
                        cryptoSettings.hasToken
                          ? 'text-green-400 bg-green-500/10 border-green-500/20'
                          : 'text-gray-400 bg-white/5 border-white/10'
                      )}>
                        <CheckCircle2 className="w-4 h-4" /> {cryptoSettings.hasToken ? 'Валиден' : 'Не задан'}
                      </span>
                    </div>

                    <div className="flex flex-col gap-1.5">
                      <span className="text-gray-500 text-xs font-bold uppercase tracking-wider">Приём платежей</span>
                      <span className={cn(
                        'font-medium flex items-center gap-2 w-max px-3 py-1 rounded-lg border',
                        cryptoSettings.enabled
                          ? 'text-green-400 bg-green-500/10 border-green-500/20'
                          : 'text-gray-400 bg-white/5 border-white/10'
                      )}>
                        <CheckCircle2 className="w-4 h-4" /> {cryptoSettings.enabled ? 'Включен' : 'Выключен'}
                      </span>
                    </div>
                  </div>

                  <div className="grid grid-cols-1 sm:grid-cols-2 gap-4 border-b border-white/5 pb-5">
                    <div className="flex flex-col gap-1.5">
                      <span className="text-gray-500 text-xs font-bold uppercase tracking-wider">Последняя проверка</span>
                      <span className="text-gray-300 font-mono bg-black/40 w-max px-3 py-1 rounded-lg border border-white/5">{formatDateTime(cryptoSettings.diagnostics.lastCheckedAt)}</span>
                    </div>
                    <div className="flex flex-col gap-1.5">
                      <span className="text-gray-500 text-xs font-bold uppercase tracking-wider">Последнее уведомление</span>
                      <span className="text-gray-300 font-mono bg-black/40 w-max px-3 py-1 rounded-lg border border-white/5">{formatDateTime(cryptoSettings.diagnostics.lastWebhookAt)}</span>
                    </div>
                  </div>

                  <div className="flex flex-col gap-1.5">
                    <span className="text-gray-500 text-xs font-bold uppercase tracking-wider">Последняя ошибка</span>
                    <span className="text-gray-400 text-xs break-words">{cryptoSettings.diagnostics.lastWebhookErrorText || '— Ошибок не зафиксировано'}</span>
                  </div>
                </div>
              </div>
            </div>
          </div>
        </>
      )}
    </motion.div>
  );
}
