/**
 * QR Code Generator
 * Wrapper around qrcode library for generating QR codes
 */

import QRCode from 'qrcode';
import { QRCalculatorData } from '../types';
import { generateQRUrl } from './qrDataEncoder';

export interface QRCodeOptions {
  /**
   * QR code width/height in pixels
   * @default 300
   */
  size?: number;

  /**
   * Error correction level
   * L: ~7% correction
   * M: ~15% correction
   * Q: ~25% correction
   * H: ~30% correction
   * @default 'M'
   */
  errorCorrectionLevel?: 'L' | 'M' | 'Q' | 'H';

  /**
   * Foreground color (dark modules)
   * @default '#1D2939' (deep-sea-blue)
   */
  color?: string;

  /**
   * Background color (light modules)
   * @default '#FFFFFF'
   */
  backgroundColor?: string;

  /**
   * Margin around QR code in modules
   * @default 4
   */
  margin?: number;
}

const DEFAULT_OPTIONS: Required<QRCodeOptions> = {
  size: 300,
  errorCorrectionLevel: 'M',
  color: '#1D2939', // deep-sea-blue from tailwind.config.js
  backgroundColor: '#FFFFFF',
  margin: 4,
};

/**
 * Generate QR code as PNG data URL
 * @param url URL to encode in QR code
 * @param options QR code generation options
 * @returns Promise resolving to data URL string
 */
export async function generateQRCodeDataURL(
  url: string,
  options: QRCodeOptions = {}
): Promise<string> {
  const opts = { ...DEFAULT_OPTIONS, ...options };

  try {
    const dataURL = await QRCode.toDataURL(url, {
      width: opts.size,
      errorCorrectionLevel: opts.errorCorrectionLevel,
      color: {
        dark: opts.color,
        light: opts.backgroundColor,
      },
      margin: opts.margin,
    });

    return dataURL;
  } catch (error) {
    console.error('Error generating QR code data URL:', error);
    throw new Error('Failed to generate QR code');
  }
}

/**
 * Generate QR code as SVG string
 * @param url URL to encode in QR code
 * @param options QR code generation options
 * @returns Promise resolving to SVG markup string
 */
export async function generateQRCodeSVG(
  url: string,
  options: QRCodeOptions = {}
): Promise<string> {
  const opts = { ...DEFAULT_OPTIONS, ...options };

  try {
    const svg = await QRCode.toString(url, {
      type: 'svg',
      width: opts.size,
      errorCorrectionLevel: opts.errorCorrectionLevel,
      color: {
        dark: opts.color,
        light: opts.backgroundColor,
      },
      margin: opts.margin,
    });

    return svg;
  } catch (error) {
    console.error('Error generating QR code SVG:', error);
    throw new Error('Failed to generate QR code SVG');
  }
}

/**
 * Generate QR code from calculator data
 * Returns both PNG data URL and SVG
 * @param data Calculator data to encode
 * @param baseUrl Base URL of the application
 * @param options QR code generation options
 * @returns Promise resolving to object with both formats and URL
 */
export async function generateCalculatorQRCode(
  data: QRCalculatorData,
  baseUrl: string = window.location.origin,
  options: QRCodeOptions = {}
): Promise<{
  dataURL: string;
  svg: string;
  url: string;
}> {
  // Generate the full URL with encoded data
  const url = generateQRUrl(data, baseUrl);

  // Generate both formats
  const [dataURL, svg] = await Promise.all([
    generateQRCodeDataURL(url, options),
    generateQRCodeSVG(url, options),
  ]);

  return {
    dataURL,
    svg,
    url,
  };
}

/**
 * Download QR code as PNG file
 * @param dataURL Data URL of the QR code
 * @param filename Filename for download
 */
export function downloadQRCode(dataURL: string, filename: string = 'qr-code.png'): void {
  try {
    const link = document.createElement('a');
    link.href = dataURL;
    link.download = filename;
    document.body.appendChild(link);
    link.click();
    document.body.removeChild(link);
  } catch (error) {
    console.error('Error downloading QR code:', error);
    throw new Error('Failed to download QR code');
  }
}

/**
 * Copy QR code to clipboard as image
 * @param dataURL Data URL of the QR code
 */
export async function copyQRCodeToClipboard(dataURL: string): Promise<void> {
  try {
    // Convert data URL to blob
    const response = await fetch(dataURL);
    const blob = await response.blob();

    // Copy to clipboard
    await navigator.clipboard.write([
      new ClipboardItem({
        [blob.type]: blob,
      }),
    ]);
  } catch (error) {
    console.error('Error copying QR code to clipboard:', error);
    throw new Error('Failed to copy QR code to clipboard');
  }
}

/**
 * Print QR code
 * @param dataURL Data URL of the QR code
 * @param title Optional title to display above QR code
 */
export function printQRCode(dataURL: string, title?: string): void {
  try {
    const printWindow = window.open('', '_blank');
    if (!printWindow) {
      throw new Error('Failed to open print window');
    }

    const doc = printWindow.document;

    // Create document structure using DOM manipulation
    const htmlEl = doc.createElement('html');
    const headEl = doc.createElement('head');
    const bodyEl = doc.createElement('body');

    // Set title
    const titleEl = doc.createElement('title');
    titleEl.textContent = `QR Code${title ? ` - ${title}` : ''}`;
    headEl.appendChild(titleEl);

    // Add styles
    const styleEl = doc.createElement('style');
    styleEl.textContent = `
      body {
        margin: 0;
        padding: 20px;
        display: flex;
        flex-direction: column;
        align-items: center;
        justify-content: center;
        font-family: system-ui, -apple-system, sans-serif;
      }
      h1 {
        margin-bottom: 20px;
        color: #1D2939;
      }
      img {
        max-width: 100%;
        height: auto;
      }
    `;
    headEl.appendChild(styleEl);

    // Add title heading if provided
    if (title) {
      const h1El = doc.createElement('h1');
      h1El.textContent = title;
      bodyEl.appendChild(h1El);
    }

    // Add QR code image
    const imgEl = doc.createElement('img');
    imgEl.src = dataURL;
    imgEl.alt = 'QR Code';
    bodyEl.appendChild(imgEl);

    // Assemble document
    htmlEl.appendChild(headEl);
    htmlEl.appendChild(bodyEl);
    doc.documentElement.replaceWith(htmlEl);

    // Wait for image to load before printing
    imgEl.onload = () => {
      printWindow.print();
    };
  } catch (error) {
    console.error('Error printing QR code:', error);
    throw new Error('Failed to print QR code');
  }
}
