'use client';

import { useState } from 'react';
import { useToast } from './ToastProvider';
import { getResponseErrorTextWithRequestId } from '@/lib/api-client';

interface ExportHtmlButtonProps {
  linkId: string;
  period: string;
  linkData?: {
    shortUrl: string;
    longUrl: string;
    title: string | null;
  };
  getExportNode?: () => HTMLElement | null;
  disabled?: boolean;
  disabledReason?: string;
}

function getSlugForFileName(shortUrl: string | undefined, fallback = 'report') {
  const safeFallback = fallback || 'report';
  if (!shortUrl) return safeFallback;

  const lastSegment = shortUrl.split('/').pop() || safeFallback;
  const normalized = lastSegment
    .trim()
    .replace(/[^a-zA-Z0-9_-]+/g, '-')
    .replace(/-+/g, '-')
    .replace(/^-+|-+$/g, '');

  return normalized || safeFallback;
}

function cloneNodeWithInlineStyles(node: Node): Node | null {
  if (node.nodeType === Node.TEXT_NODE) {
    return document.createTextNode(node.textContent || '');
  }

  if (node.nodeType !== Node.ELEMENT_NODE) {
    return null;
  }

  const element = node as Element;
  if (element instanceof HTMLElement && element.dataset.exportExclude === 'true') {
    return null;
  }

  const clone = element.cloneNode(false) as Element;
  const computed = window.getComputedStyle(element);
  let inlineStyle = '';
  for (let i = 0; i < computed.length; i += 1) {
    const property = computed.item(i);
    if (!property) continue;
    inlineStyle += `${property}:${computed.getPropertyValue(property)};`;
  }
  if (inlineStyle) {
    clone.setAttribute('style', inlineStyle);
  }

  for (const attr of Array.from(element.attributes)) {
    if (attr.name === 'class' || attr.name === 'style' || attr.name.startsWith('data-export')) {
      continue;
    }
    clone.setAttribute(attr.name, attr.value);
  }

  for (const child of Array.from(node.childNodes)) {
    const childClone = cloneNodeWithInlineStyles(child);
    if (childClone) {
      clone.appendChild(childClone);
    }
  }

  return clone;
}

function serializeNodeAsStandaloneHtml(node: HTMLElement, title: string) {
  const cloned = cloneNodeWithInlineStyles(node);
  if (!cloned || !(cloned instanceof Element)) {
    throw new Error('Не удалось подготовить HTML-экспорт');
  }

  return [
    '<!DOCTYPE html>',
    '<html lang="ru">',
    '<head>',
    '<meta charset="utf-8" />',
    '<meta name="viewport" content="width=device-width, initial-scale=1" />',
    `<title>${title}</title>`,
    '<style>',
    'html, body { margin: 0; padding: 0; background: #050505; color: #fff; font-family: "Inter", "Segoe UI", sans-serif; }',
    'body { min-height: 100vh; padding: 28px; display: flex; justify-content: center; }',
    '* { box-sizing: border-box; }',
    '</style>',
    '</head>',
    '<body>',
    '<main style="width: min(1200px, 100%);">',
    cloned.outerHTML,
    '</main>',
    '</body>',
    '</html>',
  ].join('');
}

function downloadHtmlFile(html: string, fileName: string) {
  const blob = new Blob([html], { type: 'text/html;charset=utf-8' });
  const url = URL.createObjectURL(blob);
  const anchor = document.createElement('a');
  anchor.href = url;
  anchor.download = fileName;
  document.body.appendChild(anchor);
  anchor.click();
  document.body.removeChild(anchor);
  URL.revokeObjectURL(url);
}

export default function ExportHtmlButton({
  linkId,
  period,
  linkData,
  getExportNode,
  disabled = false,
  disabledReason,
}: ExportHtmlButtonProps) {
  const toast = useToast();
  const [isGenerating, setIsGenerating] = useState(false);

  const handleExport = async () => {
    if (disabled) {
      if (disabledReason) {
        toast.info(disabledReason);
      }
      return;
    }

    setIsGenerating(true);

    try {
      const fileSlug = getSlugForFileName(linkData?.shortUrl, linkId);
      const fileName = `snaplink-report-${fileSlug}-${period}days.html`;
      const exportNode = getExportNode?.();

      if (exportNode) {
        const pageTitle = linkData?.title?.trim() || linkData?.shortUrl || 'Статистика ссылки';
        const html = serializeNodeAsStandaloneHtml(exportNode, pageTitle);
        downloadHtmlFile(html, fileName);
        toast.success('HTML успешно скачан');
        return;
      }

      const response = await fetch(`/api/links/${linkId}/stats/export-html?period=${period}`);
      if (!response.ok) {
        throw new Error(await getResponseErrorTextWithRequestId(response, 'Ошибка получения данных'));
      }

      const html = await response.text();
      downloadHtmlFile(html, fileName);
      toast.success('HTML успешно скачан');
    } catch (error) {
      const message = error instanceof Error ? error.message : 'Не удалось экспортировать HTML';
      toast.error(message);
    } finally {
      setIsGenerating(false);
    }
  };

  return (
    <button
      type="button"
      onClick={handleExport}
      disabled={disabled || isGenerating}
      title={disabled ? disabledReason : undefined}
      className="inline-flex min-h-[42px] items-center justify-center gap-2 rounded-xl border border-white/15 bg-white/[0.03] px-4 py-2.5 text-sm font-medium text-gray-200 shadow-[0_0_20px_rgba(42,171,238,0.08)] transition-all duration-300 hover:border-white/30 hover:bg-white/[0.08] hover:text-white disabled:cursor-not-allowed disabled:opacity-55"
    >
      {isGenerating ? (
        <>
          <div className="h-4 w-4 animate-spin rounded-full border-2 border-white/90 border-t-transparent" />
          Генерация...
        </>
      ) : (
        <>
          <svg className="h-4 w-4" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2">
            <path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z" />
            <polyline points="14 2 14 8 20 8" />
            <line x1="16" y1="13" x2="8" y2="13" />
            <line x1="16" y1="17" x2="8" y2="17" />
            <polyline points="10 9 9 9 8 9" />
          </svg>
          {disabled ? 'HTML недоступен' : 'Экспорт HTML'}
        </>
      )}
    </button>
  );
}
