import { useEffect, useState } from 'react';
import { emit, listen } from '@tauri-apps/api/event';
import { invoke } from '@tauri-apps/api/core';
import { getCurrentWindow, LogicalSize } from '@tauri-apps/api/window';
import {
  PrintExportPayload,
} from '../printExport';

interface PrintViewProps {
  jobId: string;
}

const waitForImages = async () => {
  const images = Array.from(document.images).filter((image) => !image.complete);

  await Promise.all(
    images.map(
      (image) =>
        new Promise<void>((resolve) => {
          image.addEventListener('load', () => resolve(), { once: true });
          image.addEventListener('error', () => resolve(), { once: true });
        })
    )
  );
};

export function PrintView({ jobId }: PrintViewProps) {
  const [payload, setPayload] = useState<PrintExportPayload | null>(null);
  const [error, setError] = useState('');

  useEffect(() => {
    const currentWindow = getCurrentWindow();
    let timeoutId = 0;
    let cleanup = () => {};

    void (async () => {
      cleanup = await listen<PrintExportPayload>(
        'print-export-payload',
        (event) => {
          window.clearTimeout(timeoutId);
          setPayload(event.payload);
        },
        {
          target: { kind: 'WebviewWindow', label: currentWindow.label },
        }
      );

      await emit('print-export-ready', { jobId });

      timeoutId = window.setTimeout(() => {
        setError('Print data was not received. Please close this window and try exporting again.');
      }, 5000);
    })();

    return () => {
      window.clearTimeout(timeoutId);
      cleanup();
    };
  }, [jobId]);

  useEffect(() => {
    if (!payload) return;

    const currentWindow = getCurrentWindow();
    let cancelled = false;
    let printFlowStarted = false;
    let lostFocusDuringPrint = false;
    let closeTimerId = 0;
    let destroyIntervalId = 0;
    let removeFocusListener = () => {};

    document.title = payload.fileName;

    const closePrintWindow = () => {
      if (cancelled) return;

      if (destroyIntervalId) return;

      window.clearTimeout(closeTimerId);
      closeTimerId = window.setTimeout(() => {
        destroyIntervalId = window.setInterval(() => {
          void currentWindow.destroy().catch(() => undefined);
        }, 250);

        void currentWindow.destroy().catch(() => undefined);
      }, 150);
    };

    const handleAfterPrint = () => {
      closePrintWindow();
    };

    window.addEventListener('afterprint', handleAfterPrint);

    void (async () => {
      try {
        removeFocusListener = await currentWindow.onFocusChanged(({ payload: focused }) => {
          if (!printFlowStarted) return;

          if (!focused) {
            lostFocusDuringPrint = true;
            return;
          }

          if (lostFocusDuringPrint) {
            closePrintWindow();
          }
        });

        if ('fonts' in document) {
          await document.fonts.ready;
        }
        await waitForImages();
        await new Promise<void>((resolve) =>
          requestAnimationFrame(() => requestAnimationFrame(() => resolve()))
        );

        if (cancelled) return;

        await currentWindow.show().catch(() => undefined);
        await currentWindow.setFocus().catch(() => undefined);

        window.setTimeout(async () => {
          if (cancelled) return;

          try {
            printFlowStarted = true;
            await invoke('plugin:webview|print', {
              label: currentWindow.label,
            });
            await currentWindow
              .setSize(new LogicalSize(520, 260))
              .catch(() => undefined);
            closePrintWindow();
          } catch (err) {
            console.error('Native webview print failed, falling back to window.print():', err);
            printFlowStarted = true;
            window.print();
          }
        }, 120);
      } catch (err) {
        console.error('Failed to initialize print view:', err);
        setError('The print view could not be prepared. Please close this window and try again.');
      }
    })();

    return () => {
      cancelled = true;
      window.clearTimeout(closeTimerId);
      window.clearInterval(destroyIntervalId);
      removeFocusListener();
      window.removeEventListener('afterprint', handleAfterPrint);
    };
  }, [jobId, payload]);

  if (error) {
    return (
      <div className="min-h-screen bg-gray-100 px-8 py-12 text-gray-900">
        <div className="mx-auto max-w-2xl rounded-2xl bg-white p-8 shadow-sm">
          <h1 className="mb-3 text-2xl font-semibold">Print Export Failed</h1>
          <p>{error}</p>
        </div>
      </div>
    );
  }

  if (!payload) {
    return (
      <div className="min-h-screen bg-gray-100 px-8 py-12 text-gray-900">
        <div className="mx-auto max-w-2xl rounded-2xl bg-white p-8 shadow-sm">
          Preparing print view...
        </div>
      </div>
    );
  }

  return (
    <>
      <style>{`
        :root {
          color-scheme: light;
        }

        body {
          margin: 0;
          background: #e5e7eb;
          color: #0f172a;
        }

        @page {
          size: A4;
          margin: 18mm 16mm 18mm 16mm;
        }

        @media print {
          body {
            background: #ffffff;
          }

          .print-shell {
            display: block !important;
          }

          .print-status {
            display: none !important;
          }
        }
      `}</style>
      <div className="print-status min-h-screen bg-slate-100 px-6 py-6 text-slate-900">
        <div className="mx-auto flex max-w-md items-center gap-4 rounded-2xl bg-white px-5 py-4 shadow-lg">
          <div className="h-5 w-5 animate-spin rounded-full border-2 border-slate-200 border-t-slate-600" />
          <div>
            <div className="text-sm font-semibold">Opening system print dialog...</div>
            <div className="text-sm text-slate-500">{payload.fileName}</div>
          </div>
        </div>
      </div>
      <div className="print-shell absolute left-[-200vw] top-0 min-h-screen w-[820px] bg-gray-200 px-6 py-8 print:static print:min-h-0 print:w-auto print:bg-white print:px-0 print:py-0">
        <article
          className="mx-auto min-h-[calc(100vh-4rem)] max-w-[820px] rounded-[20px] bg-white px-14 py-12 text-slate-900 shadow-xl print:min-h-0 print:max-w-none print:rounded-none print:px-0 print:py-0 print:shadow-none"
          style={{
            fontFamily: `"${payload.previewFont}", Georgia, serif`,
            fontSize: `${payload.previewFontSize}px`,
            lineHeight: 1.7,
          }}
        >
          <style>{`
            .print-note {
              color: #0f172a;
            }

            .print-note h1,
            .print-note h2,
            .print-note h3 {
              color: #020617;
              font-weight: 700;
              page-break-after: avoid;
            }

            .print-note h1 {
              font-size: 2em;
              line-height: 1.15;
              margin: 0 0 1.35em;
              letter-spacing: -0.015em;
              text-align: center;
            }

            .print-note h2 {
              font-size: 1.55em;
              line-height: 1.2;
              margin: 1.25em 0 0.45em;
            }

            .print-note h3 {
              font-size: 1.25em;
              line-height: 1.3;
              margin: 1.1em 0 0.4em;
            }

            .print-note p {
              margin: 0 0 0.9em;
            }

            .print-note ul,
            .print-note ol {
              margin: 0.75em 0 1em;
              padding-left: 1.7em;
              list-style-position: outside;
            }

            .print-note ul {
              list-style-type: disc;
            }

            .print-note ol {
              list-style-type: decimal;
            }

            .print-note li {
              margin: 0.28em 0;
              padding-left: 0.18em;
            }

            .print-note li > p {
              margin: 0;
            }

            .print-note li::marker {
              color: #334155;
            }

            .print-note blockquote {
              margin: 1.15em 0;
              padding-left: 1em;
              border-left: 3px solid #cbd5e1;
              color: #475569;
              font-style: italic;
            }

            .print-note blockquote > :first-child {
              margin-top: 0;
            }

            .print-note blockquote > :last-child {
              margin-bottom: 0;
            }

            .print-note code {
              font-family: "Source Code Pro", "Courier New", monospace;
              font-size: 0.92em;
            }

            .print-note :not(pre) > code {
              padding: 0.08em 0.28em;
              border-radius: 4px;
              border: 1px solid #dbe4f0;
              background: #f8fafc;
              color: #1e293b;
            }

            .print-note pre {
              margin: 1em 0 1.15em;
              padding: 0.9em 1em;
              border-radius: 10px;
              background: #f8fafc;
              border: 1px solid #e2e8f0;
              color: #0f172a;
              white-space: pre-wrap;
              overflow-wrap: anywhere;
              page-break-inside: avoid;
            }

            .print-note pre code {
              font-size: 0.92em;
              line-height: 1.55;
            }

            .print-note a {
              color: #1d4ed8;
              text-decoration: underline;
            }

            .print-note img {
              display: block;
              max-width: 100%;
              height: auto;
              margin: 1.25em auto;
              border-radius: 10px;
              page-break-inside: avoid;
            }

            .print-note hr {
              border: 0;
              border-top: 1px solid #cbd5e1;
              margin: 1.6em 0;
            }
          `}</style>
          <div
            className="print-note"
            dangerouslySetInnerHTML={{ __html: payload.html }}
          />
        </article>
      </div>
    </>
  );
}
