import React, { useState, useMemo, useEffect, useRef } from 'react';
import ReactDOM from 'react-dom/client';

// ============================================================================
// TYPES (from types.ts)
// ============================================================================

interface LineItem {
  id: string;
  description: string;
  quantity: number;
  price: number;
}

// ============================================================================
// COMPONENTS (from components/*.tsx)
// ============================================================================

// Icon Component (from components/Icon.tsx)
interface IconProps {
  path: string;
  className?: string;
}

const Icon: React.FC<IconProps> = ({ path, className = 'w-6 h-6' }) => (
  <svg
    xmlns="http://www.w3.org/2000/svg"
    viewBox="0 0 24 24"
    fill="currentColor"
    className={className}
  >
    <path
      fillRule="evenodd"
      d={path}
      clipRule="evenodd"
    />
  </svg>
);

// LogoUploader Component (from components/LogoUploader.tsx)
interface LogoUploaderProps {
  logoUrl: string | null;
  setLogoUrl: (url: string | null) => void;
}

const LogoUploader: React.FC<LogoUploaderProps> = ({ logoUrl, setLogoUrl }) => {
  const fileInputRef = useRef<HTMLInputElement>(null);

  useEffect(() => {
    // Cleanup object URL to prevent memory leaks
    return () => {
      if (logoUrl && logoUrl.startsWith('blob:')) {
        URL.revokeObjectURL(logoUrl);
      }
    };
  }, [logoUrl]);

  const handleFileChange = (event: React.ChangeEvent<HTMLInputElement>) => {
    const file = event.target.files?.[0];
    if (file) {
      if (logoUrl && logoUrl.startsWith('blob:')) {
        URL.revokeObjectURL(logoUrl);
      }
      setLogoUrl(URL.createObjectURL(file));
    }
  };

  const handleRemoveLogo = (e: React.MouseEvent<HTMLButtonElement>) => {
    e.stopPropagation();
    if (logoUrl) {
       if (logoUrl.startsWith('blob:')) {
        URL.revokeObjectURL(logoUrl);
      }
      setLogoUrl(null);
      if(fileInputRef.current) {
        fileInputRef.current.value = "";
      }
    }
  };

  const triggerFileInput = () => {
    fileInputRef.current?.click();
  };

  return (
    <div className="w-32 h-32 print:w-24 print:h-24">
      <input
        type="file"
        accept="image/png, image/jpeg, image/svg+xml"
        ref={fileInputRef}
        onChange={handleFileChange}
        className="hidden"
      />
      {logoUrl ? (
        <div className="relative w-full h-full group">
          <img src={logoUrl} alt="Logotipo de la Empresa" className="w-full h-full object-contain" />
          <button
            onClick={handleRemoveLogo}
            className="absolute top-1 right-1 bg-red-500 text-white rounded-full p-1 opacity-0 group-hover:opacity-100 transition-opacity duration-200 print:hidden"
            aria-label="Eliminar logotipo"
          >
            <Icon path="M6 18L18 6M6 6l12 12" className="w-4 h-4" />
          </button>
        </div>
      ) : (
        <div
          onClick={triggerFileInput}
          className="w-full h-full bg-slate-100 rounded-lg border-2 border-dashed border-slate-300 flex flex-col items-center justify-center text-slate-400 hover:bg-slate-200 hover:border-slate-400 cursor-pointer transition-colors print:hidden"
        >
          <Icon path="M2.25 15.75l5.159-5.159a2.25 2.25 0 013.182 0l5.159 5.159m-1.5-1.5l1.409-1.409a2.25 2.25 0 013.182 0l2.909 2.909m-18 3.75h16.5a1.5 1.5 0 001.5-1.5V6a1.5 1.5 0 00-1.5-1.5H3.75A1.5 1.5 0 002.25 6v12a1.5 1.5 0 001.5 1.5zm10.5-11.25h.008v.008h-.008V8.25zm.375 0a.375.375 0 11-.75 0 .375.375 0 01.75 0z" className="w-10 h-10 mb-2"/>
          <span className="text-sm font-semibold">Subir Logotipo</span>
        </div>
      )}
    </div>
  );
};


// LineItemRow Component (from components/LineItemRow.tsx)
interface LineItemRowProps {
  item: LineItem;
  onUpdate: (id: string, newValues: Partial<LineItem>) => void;
  onRemove: (id: string) => void;
  currencyFormatter: Intl.NumberFormat;
}

const LineItemRow: React.FC<LineItemRowProps> = ({ item, onUpdate, onRemove, currencyFormatter }) => {
  const handleInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {
    const { name, value } = e.target;
    let numericValue: string | number = name === 'quantity' || name === 'price' ? parseFloat(value) : value;
    if (isNaN(numericValue as number)) {
        numericValue = 0;
    }
    onUpdate(item.id, { [name]: numericValue });
  };

  const lineTotal = item.quantity * item.price;

  return (
    <div className="grid grid-cols-12 gap-2 p-2 items-center hover:bg-slate-100 rounded-lg animate__animated animate__fadeIn">
      <div className="col-span-12 md:col-span-5">
        <input
          type="text"
          name="description"
          value={item.description}
          onChange={handleInputChange}
          placeholder="Descripción del artículo"
          className="w-full p-2 border border-slate-200 rounded-md focus:ring-2 focus:ring-indigo-500 focus:border-indigo-500 transition"
        />
      </div>
      <div className="col-span-6 md:col-span-2">
        <input
          type="number"
          name="quantity"
          value={item.quantity}
          onChange={handleInputChange}
          min="0"
          placeholder="Cantidad"
          className="w-full p-2 border border-slate-200 rounded-md focus:ring-2 focus:ring-indigo-500 focus:border-indigo-500 transition"
        />
      </div>
      <div className="col-span-6 md:col-span-2">
        <input
          type="number"
          name="price"
          value={item.price}
          onChange={handleInputChange}
          min="0"
          step="0.01"
          placeholder="Precio"
          className="w-full p-2 border border-slate-200 rounded-md focus:ring-2 focus:ring-indigo-500 focus:border-indigo-500 transition"
        />
      </div>
      <div className="col-span-10 md:col-span-2 text-right text-slate-800 font-medium pr-2">
        {currencyFormatter.format(lineTotal)}
      </div>
      <div className="col-span-2 md:col-span-1 text-center">
        <button
          onClick={() => onRemove(item.id)}
          className="text-slate-400 hover:text-red-500 p-2 rounded-full transition-colors duration-200"
          aria-label="Eliminar artículo"
        >
          <Icon path="M12 2.25c-5.385 0-9.75 4.365-9.75 9.75s4.365 9.75 9.75 9.75 9.75-4.365 9.75-9.75S17.385 2.25 12 2.25zm-1.72 6.97a.75.75 0 10-1.06 1.06L10.94 12l-1.72 1.72a.75.75 0 101.06 1.06L12 13.06l1.72 1.72a.75.75 0 101.06-1.06L13.06 12l1.72-1.72a.75.75 0 10-1.06-1.06L12 10.94l-1.72-1.72z" className="w-6 h-6" />
        </button>
      </div>
    </div>
  );
};

// ============================================================================
// MAIN APP COMPONENT (from App.tsx)
// ============================================================================

// Declara las variables globales para las librerías cargadas por CDN
declare const jspdf: any;
declare const html2canvas: any;

const App: React.FC = () => {
  const quoteRef = useRef<HTMLDivElement>(null);

  const getInitialState = () => {
    const savedData = localStorage.getItem('quoteData');
    if (savedData) {
      try {
        const parsed = JSON.parse(savedData);
         // Asegura que los datos cargados no sean nulos para los estados iniciales
        if (parsed) {
          return {
            ...parsed,
            lineItems: parsed.lineItems || [],
            taxRate: parsed.taxRate ?? 16,
            currency: parsed.currency || 'MXN',
            logoUrl: parsed.logoUrl || null,
            quoteNumber: parsed.quoteNumber || '12345',
            clientName: parsed.clientName || '',
            clientAddress: parsed.clientAddress || '',
            clientEmail: parsed.clientEmail || '',
            quoteDate: parsed.quoteDate || new Date().toISOString().split('T')[0],
            validUntilDate: parsed.validUntilDate || '',
            notes: parsed.notes || 'Gracias por su negocio. Si tiene alguna pregunta, no dude en contactarnos.',
          };
        }
      } catch (e) {
        console.error("No se pudieron cargar los datos guardados, usando valores por defecto.", e);
      }
    }
    // Devuelve el estado por defecto si no hay nada guardado o los datos son inválidos
    return {
      lineItems: [
        { id: crypto.randomUUID(), description: 'Servicios de Diseño Web', quantity: 1, price: 2500 },
        { id: crypto.randomUUID(), description: 'Hosting (1 año)', quantity: 1, price: 300 },
      ],
      taxRate: 16,
      currency: 'MXN',
      logoUrl: null,
      quoteNumber: '12345',
      clientName: '',
      clientAddress: '',
      clientEmail: '',
      quoteDate: new Date().toISOString().split('T')[0],
      validUntilDate: '',
      notes: 'Gracias por su negocio. Si tiene alguna pregunta, no dude en contactarnos.',
    };
  };

  const [lineItems, setLineItems] = useState<LineItem[]>(() => getInitialState().lineItems);
  const [taxRate, setTaxRate] = useState<number>(() => getInitialState().taxRate);
  const [currency, setCurrency] = useState<'USD' | 'EUR' | 'GBP' | 'JPY' | 'MXN'>(() => getInitialState().currency);
  const [logoUrl, setLogoUrl] = useState<string | null>(() => getInitialState().logoUrl);
  const [quoteNumber, setQuoteNumber] = useState<string>(() => getInitialState().quoteNumber);
  const [clientName, setClientName] = useState<string>(() => getInitialState().clientName);
  const [clientAddress, setClientAddress] = useState<string>(() => getInitialState().clientAddress);
  const [clientEmail, setClientEmail] = useState<string>(() => getInitialState().clientEmail);
  const [quoteDate, setQuoteDate] = useState<string>(() => getInitialState().quoteDate);
  const [validUntilDate, setValidUntilDate] = useState<string>(() => getInitialState().validUntilDate);
  const [notes, setNotes] = useState<string>(() => getInitialState().notes);

  useEffect(() => {
    const dataToSave = {
      lineItems,
      taxRate,
      currency,
      logoUrl,
      quoteNumber,
      clientName,
      clientAddress,
      clientEmail,
      quoteDate,
      validUntilDate,
      notes,
    };
    localStorage.setItem('quoteData', JSON.stringify(dataToSave));
  }, [lineItems, taxRate, currency, logoUrl, quoteNumber, clientName, clientAddress, clientEmail, quoteDate, validUntilDate, notes]);

  const currencyFormatter = useMemo(() => {
    return new Intl.NumberFormat('es-MX', { style: 'currency', currency });
  }, [currency]);

  const subtotal = useMemo(() => {
    return lineItems.reduce((acc, item) => acc + item.quantity * item.price, 0);
  }, [lineItems]);

  const taxAmount = useMemo(() => {
    return subtotal * (taxRate / 100);
  }, [subtotal, taxRate]);

  const total = useMemo(() => {
    return subtotal + taxAmount;
  }, [subtotal, taxAmount]);

  const addLineItem = () => {
    setLineItems([...lineItems, { id: crypto.randomUUID(), description: '', quantity: 1, price: 0 }]);
  };

  const updateLineItem = (id: string, newValues: Partial<LineItem>) => {
    setLineItems(lineItems.map(item => (item.id === id ? { ...item, ...newValues } : item)));
  };

  const removeLineItem = (id: string) => {
    setLineItems(lineItems.filter(item => item.id !== id));
  };
  
  const handlePrint = () => {
    window.print();
  };

  const handleExportPdf = () => {
    const input = quoteRef.current;
    if (input) {
      html2canvas(input, {
        scale: 2,
        useCORS: true,
        // Agrega un tiempo de espera para asegurar que las imágenes (como el logotipo) se carguen
        // antes de que se renderice el canvas. Esto mejora la fiabilidad de la exportación.
        imageTimeout: 5000,
      }).then(canvas => {
          const imgData = canvas.toDataURL('image/png');
          const pdf = new jspdf.jsPDF({
            orientation: 'p',
            unit: 'pt',
            format: 'letter',
          });
          
          const pdfWidth = pdf.internal.pageSize.getWidth();
          const imgProps= pdf.getImageProperties(imgData);
          const pdfHeight = (imgProps.height * pdfWidth) / imgProps.width;
          
          pdf.addImage(imgData, 'PNG', 0, 0, pdfWidth, pdfHeight);
          pdf.save(`cotizacion-${quoteNumber}.pdf`);
      }).catch(err => {
          console.error("Error al exportar a PDF:", err);
      });
    }
  };


  return (
    <div className="container mx-auto p-4 md:p-8 font-sans">
      <div className="flex justify-between items-center mb-8 print:hidden">
        <h1 className="text-3xl font-bold text-slate-800">Generador de Cotizaciones</h1>
        <div className="flex gap-2">
          <button onClick={handleExportPdf} className="bg-green-500 hover:bg-green-600 text-white font-bold py-2 px-4 rounded-lg inline-flex items-center transition-colors">
            <Icon path="M3 16.5v2.25A2.25 2.25 0 005.25 21h13.5A2.25 2.25 0 0021 18.75V16.5M16.5 12L12 16.5m0 0L7.5 12m4.5 4.5V3" className="w-5 h-5 mr-2" />
            <span>Exportar a PDF</span>
          </button>
          <button onClick={handlePrint} className="bg-indigo-500 hover:bg-indigo-600 text-white font-bold py-2 px-4 rounded-lg inline-flex items-center transition-colors">
            <Icon path="M6.72 13.829c-.24.03-.48.062-.72.096m.72-.096a42.415 42.415 0 0110.56 0m-10.56 0L6 18.25m0 0a2.25 2.25 0 01-2.25 2.25H3.75A2.25 2.25 0 011.5 18.25V6.75A2.25 2.25 0 013.75 4.5h16.5a2.25 2.25 0 012.25 2.25v11.5a2.25 2.25 0 01-2.25 2.25h-2.25m-13.5-13.5v-1.125c0-.621.504-1.125 1.125-1.125h11.25c.621 0 1.125.504 1.125 1.125v1.125m-13.5 0s-1.125.225-1.125 1.125v11.25c0 .9 1.125 1.125 1.125 1.125m13.5 0s1.125-.225 1.125-1.125V6.375c0-.9-1.125-1.125-1.125-1.125" className="w-5 h-5 mr-2" />
            <span>Imprimir</span>
          </button>
        </div>
      </div>

      <div ref={quoteRef} className="bg-white rounded-lg shadow-lg p-8 md:p-12 print:shadow-none print:p-0">
        <header className="flex justify-between items-start mb-10 pb-6 border-b-2 border-slate-100">
          <LogoUploader logoUrl={logoUrl} setLogoUrl={setLogoUrl} />
          <div className="text-right">
            <h2 className="text-3xl font-bold uppercase text-slate-800">Cotización</h2>
            <div className="flex items-center justify-end mt-2">
                <span className="text-slate-500 font-medium mr-2">#</span>
                <input 
                    type="text" 
                    value={quoteNumber} 
                    onChange={(e) => setQuoteNumber(e.target.value)} 
                    className="p-1 w-28 text-right font-semibold text-slate-700 border-b-2 border-transparent focus:border-indigo-500 focus:outline-none transition" 
                />
            </div>
          </div>
        </header>

        <section className="grid grid-cols-1 md:grid-cols-2 gap-8 mb-10">
            <div>
                <h3 className="text-lg font-semibold text-slate-600 mb-2">Cliente:</h3>
                 <input 
                    type="text"
                    value={clientName} 
                    onChange={(e) => setClientName(e.target.value)} 
                    placeholder="Nombre del Cliente"
                    className="w-full p-2 mb-2 border border-slate-200 rounded-md focus:ring-2 focus:ring-indigo-500 focus:border-indigo-500 transition" 
                />
                 <textarea 
                    value={clientAddress} 
                    onChange={(e) => setClientAddress(e.target.value)} 
                    placeholder="Dirección del Cliente"
                    rows={3}
                    className="w-full p-2 border border-slate-200 rounded-md focus:ring-2 focus:ring-indigo-500 focus:border-indigo-500 transition" 
                />
                <input 
                    type="email"
                    value={clientEmail} 
                    onChange={(e) => setClientEmail(e.target.value)} 
                    placeholder="Correo Electrónico del Cliente"
                    className="w-full p-2 mt-2 border border-slate-200 rounded-md focus:ring-2 focus:ring-indigo-500 focus:border-indigo-500 transition" 
                />
            </div>
            <div className="text-left md:text-right">
                <div className="flex items-center justify-start md:justify-end mb-2">
                    <label className="text-slate-600 font-semibold w-32 text-left">Fecha de Emisión:</label>
                    <input 
                        type="date" 
                        value={quoteDate} 
                        onChange={(e) => setQuoteDate(e.target.value)} 
                        className="p-1 w-40 text-right font-medium text-slate-700 border-b-2 border-transparent focus:border-indigo-500 focus:outline-none transition" 
                    />
                </div>
                <div className="flex items-center justify-start md:justify-end">
                    <label className="text-slate-600 font-semibold w-32 text-left">Válido Hasta:</label>
                     <input 
                        type="date" 
                        value={validUntilDate} 
                        onChange={(e) => setValidUntilDate(e.target.value)} 
                        className="p-1 w-40 text-right font-medium text-slate-700 border-b-2 border-transparent focus:border-indigo-500 focus:outline-none transition" 
                    />
                </div>
            </div>
        </section>

        <section className="mb-10">
          <div className="hidden md:grid grid-cols-12 gap-2 text-left font-bold text-slate-500 uppercase text-sm pb-2 border-b-2 border-slate-200">
            <div className="col-span-5">Descripción</div>
            <div className="col-span-2">Cantidad</div>
            <div className="col-span-2">Precio Unitario</div>
            <div className="col-span-2 text-right">Total</div>
            <div className="col-span-1"></div>
          </div>
          <div className="flex flex-col gap-2 mt-4">
              {lineItems.map(item => (
                <LineItemRow
                  key={item.id}
                  item={item}
                  onUpdate={updateLineItem}
                  onRemove={removeLineItem}
                  currencyFormatter={currencyFormatter}
                />
              ))}
          </div>
           <button onClick={addLineItem} className="mt-4 bg-slate-100 hover:bg-slate-200 text-slate-600 font-bold py-2 px-4 rounded-lg inline-flex items-center transition-colors print:hidden">
                <Icon path="M12 4.5v15m7.5-7.5h-15" className="w-5 h-5 mr-2" />
                <span>Agregar Artículo</span>
          </button>
        </section>

        <section className="flex justify-end mb-10">
            <div className="w-full md:w-1/2 lg:w-1/3">
                <div className="flex justify-between items-center mb-2">
                    <span className="text-slate-600 font-medium">Subtotal:</span>
                    <span className="text-slate-800 font-bold text-lg">{currencyFormatter.format(subtotal)}</span>
                </div>
                <div className="flex justify-between items-center mb-2 pb-2 border-b-2">
                    <div className="flex items-center">
                        <span className="text-slate-600 font-medium mr-2">I.V.A. (%):</span>
                        <input 
                            type="number" 
                            value={taxRate} 
                            onChange={(e) => setTaxRate(parseFloat(e.target.value) || 0)} 
                            className="w-16 p-1 text-right font-medium text-slate-700 border border-slate-200 rounded-md focus:ring-2 focus:ring-indigo-500 focus:border-indigo-500 transition"
                        />
                    </div>
                    <span className="text-slate-800 font-bold text-lg">{currencyFormatter.format(taxAmount)}</span>
                </div>
                 <div className="flex justify-between items-center mt-4">
                    <span className="text-slate-800 font-bold text-xl">Total:</span>
                    <span className="text-indigo-600 font-bold text-2xl">{currencyFormatter.format(total)}</span>
                </div>
            </div>
        </section>

        <section>
            <h3 className="text-lg font-semibold text-slate-600 mb-2">Notas:</h3>
            <textarea 
                value={notes} 
                onChange={(e) => setNotes(e.target.value)}
                rows={4}
                className="w-full p-2 border border-slate-200 rounded-md focus:ring-2 focus:ring-indigo-500 focus:border-indigo-500 transition"
            />
        </section>

        <footer className="mt-12 pt-6 border-t-2 border-slate-100 text-center text-slate-500 text-sm">
            <p>Cotización generada el {new Date(quoteDate).toLocaleDateString('es-MX', { year: 'numeric', month: 'long', day: 'numeric' })}.</p>
        </footer>
      </div>
    </div>
  );
};


// ============================================================================
// RENDER THE APP (original index.tsx content)
// ============================================================================

const rootElement = document.getElementById('root');
if (!rootElement) {
  throw new Error("Could not find root element to mount to");
}

const root = ReactDOM.createRoot(rootElement);
root.render(
  <React.StrictMode>
    <App />
  </React.StrictMode>
);