/**
 * Reprint Labels Page
 * Allows reprinting labels for inventory items from GRN or Production Order
 */

'use client';

import { useState } from 'react';
import { useSearchParams, useRouter } from 'next/navigation';
import { useQuery } from '@tanstack/react-query';
import { inventoryAPI } from '@/lib/api/inventory';
import { Button, Card, CardHeader, CardTitle, CardContent, Table, TableHeader, TableBody, TableRow, TableHead, TableCell, Badge, LoadingSpinner } from '@/components/ui';

// Simple checkbox component
function Checkbox({ checked, onChange, disabled }) {
  return (
    <input
      type="checkbox"
      checked={checked}
      onChange={onChange}
      disabled={disabled}
      className="w-4 h-4 text-blue-600 border-gray-300 rounded focus:ring-blue-500 dark:border-gray-600 dark:bg-gray-700"
    />
  );
}
import { ArrowLeft, Printer, Package } from 'lucide-react';
import toast from 'react-hot-toast';
import { usePrintLabel } from '@/hooks/usePrintLabel';
import { labelPrintingAPI } from '@/lib/api/labelPrinting';
import { getAvailablePrinters, createPrintBatchJob, getPrintJobStatus } from '@/lib/utils/printerClient';
import PrinterSelect from '@/components/features/label-printing/PrinterSelect';

export default function ReprintLabelsPage() {
  const router = useRouter();
  const searchParams = useSearchParams();
  const source = searchParams.get('source'); // 'GRN' or 'PRODUCTION'
  const referenceId = searchParams.get('reference_id'); // GRN ID or Production Order ID

  const [selectedItems, setSelectedItems] = useState(new Set());
  const { isPrinting, selectedPrinterName, setSelectedPrinterName } = usePrintLabel();

  // Fetch inventory items for this GRN or Production Order
  const { data, isLoading, error } = useQuery({
    queryKey: ['reprint-items', source, referenceId],
    queryFn: async () => {
      if (!source || !referenceId) {
        return { items: [], pagination: {} };
      }

      // Fetch all items for this source/reference (excluding SOLD items)
      // We'll filter SOLD items on the client side
      const params = {
        source,
        source_reference_id: parseInt(referenceId),
        limit: 1000, // Get all items for reprinting
      };

      const response = await inventoryAPI.listItems(params);
      const items = response?.data?.items || response?.data || [];
      
      // Filter out SOLD items - cannot reprint sold items
      const reprintableItems = items.filter(item => item.status !== 'SOLD');
      
      return { items, reprintableItems, pagination: response?.data?.pagination || {} };
    },
    enabled: !!source && !!referenceId,
  });

  const items = data?.items || [];
  const reprintableItems = data?.reprintableItems || [];

  const handleSelectAll = (checked) => {
    if (checked) {
      setSelectedItems(new Set(reprintableItems.map(item => item.id)));
    } else {
      setSelectedItems(new Set());
    }
  };

  const handleSelectItem = (itemId, checked) => {
    const newSelected = new Set(selectedItems);
    if (checked) {
      newSelected.add(itemId);
    } else {
      newSelected.delete(itemId);
    }
    setSelectedItems(newSelected);
  };

  const handlePrintSelected = async () => {
    if (!selectedPrinterName) {
      toast.error('Please select a printer');
      return;
    }

    if (selectedItems.size === 0) {
      toast.error('Please select at least one item to print');
      return;
    }

    const itemsToPrint = reprintableItems.filter((item) =>
      selectedItems.has(item.id),
    );

    // Resolve printer details to get DPI and label size for ZPL generation
    let printerDpi = 203;
    try {
      const printers = await getAvailablePrinters();
      const target = printers.find(
        (p) =>
          p.name?.toLowerCase() === selectedPrinterName.toLowerCase(),
      );
      if (target) {
        printerDpi = target.dpi || 203;
      }
    } catch (error) {
      console.warn('Failed to resolve printer DPI, falling back to 203dpi', error);
    }

    const labelLength = 2.5;
    // Use a safer default width (4") to avoid content touching label edges
    const labelWidth = 4;

    // Generate ZPL for all selected items in one backend call
    let batchItems = [];
    try {
      const response = await labelPrintingAPI.generateBatchInventoryItemZPL(
        itemsToPrint.map((item) => item.id),
        { dpi: printerDpi, labelLength, labelWidth },
      );
      const data = response?.data || response;
      batchItems = data?.items || [];
    } catch (error) {
      console.error('Failed to generate batch ZPL:', error);
      toast.error(
        error?.message ||
          'Failed to generate label data for selected items.',
      );
      return;
    }

    // Map batch ZPL into print service batch items
    const serviceBatchItems = batchItems.map((item) => ({
      itemId: String(item.inventoryItemId),
      zpl: item.zplData,
    }));

    // Enqueue batch job in local print service
    let job;
    try {
      job = await createPrintBatchJob(selectedPrinterName, serviceBatchItems);
      toast.success(
        `Sent ${serviceBatchItems.length} label${serviceBatchItems.length !== 1 ? 's' : ''} to print queue for ${selectedPrinterName}`,
      );
    } catch (error) {
      console.error('Failed to create batch print job:', error);
      toast.error(
        error?.message ||
          'Failed to send batch print job to local print service.',
      );
      return;
    }

    // Poll job status until completion (or timeout)
    const jobId = job.jobId;
    const startTime = Date.now();
    const maxDurationMs = 5 * 60 * 1000; // 5 minutes max
    let finalStatus = null;

    try {
      // eslint-disable-next-line no-constant-condition
      while (true) {
        // Stop polling after max duration
        if (Date.now() - startTime > maxDurationMs) {
          console.warn('Print job status polling timed out', { jobId });
          toast.error(
            'Print job is taking longer than expected. Please check the printer status manually.',
          );
          break;
        }

        // eslint-disable-next-line no-await-in-loop
        const status = await getPrintJobStatus(jobId);

        if (!status || status.success === false) {
          console.warn('Unexpected print job status payload', status);
          break;
        }

        const terminalStates = ['Completed', 'CompletedWithErrors', 'Failed'];

        if (terminalStates.includes(status.status)) {
          finalStatus = status;
          break;
        }

        // Wait before next poll
        // eslint-disable-next-line no-await-in-loop
        await new Promise((resolve) => setTimeout(resolve, 1500));
      }
    } catch (error) {
      console.error('Error while polling print job status:', error);
      toast.error(
        error?.message ||
          'Error while tracking print job status. Some labels may still be printing.',
      );
    }

    // Interpret final status if available
    if (finalStatus) {
      const { totalItems, successCount, failedCount } = finalStatus;

      if (successCount === totalItems && failedCount === 0) {
        toast.success(
          `All ${successCount} labels printed successfully on ${selectedPrinterName}`,
        );
      } else if (successCount > 0 && failedCount > 0) {
        toast.success(
          `${successCount} labels printed successfully, ${failedCount} failed. Please check printer and retry failed ones.`,
        );
      } else if (successCount === 0 && failedCount > 0) {
        toast.error(
          `All ${failedCount} labels failed to print. Please check printer and try again.`,
        );
      }
    }

    // Clear selection after submitting batch (regardless of outcome)
    setSelectedItems(new Set());
  };

  if (isLoading) {
    return (
      <div className="container mx-auto p-6">
        <div className="flex justify-center py-12">
          <LoadingSpinner size="lg" />
        </div>
      </div>
    );
  }

  if (error) {
    return (
      <div className="container mx-auto p-6">
        <div className="text-center py-12 text-red-600 dark:text-red-400">
          Error loading items. Please try again.
        </div>
      </div>
    );
  }

  return (
    <div className="container mx-auto p-6 space-y-6">
      {/* Header */}
      <div className="flex items-center justify-between">
        <div className="flex items-center gap-4">
          <Button
            variant="outline"
            onClick={() => router.back()}
            className="flex items-center gap-2"
          >
            <ArrowLeft className="w-4 h-4" />
            Back
          </Button>
          <div>
            <h1 className="text-3xl font-bold text-gray-900 dark:text-white">Reprint Labels</h1>
            <p className="mt-1 text-sm text-gray-600 dark:text-gray-400">
              {source === 'GRN' ? 'GRN' : 'Production Order'} #{referenceId}
            </p>
          </div>
        </div>
      </div>

      {/* Info Card */}
      <Card>
        <CardContent className="pt-6">
          <div className="bg-blue-50 dark:bg-blue-950 border border-blue-200 dark:border-blue-800 rounded-lg p-4">
            <p className="text-sm text-blue-900 dark:text-blue-100">
              <strong>Note:</strong> Only items that haven't been sold can be reprinted. 
              Sold items are excluded from this list.
            </p>
            <p className="text-sm text-blue-800 dark:text-blue-200 mt-2">
              Found <strong>{reprintableItems.length}</strong> reprintable item{reprintableItems.length !== 1 ? 's' : ''} 
              {items.length !== reprintableItems.length && (
                <span className="text-gray-600 dark:text-gray-400">
                  {' '}({items.length - reprintableItems.length} sold item{(items.length - reprintableItems.length) !== 1 ? 's' : ''} excluded)
                </span>
              )}
            </p>
          </div>
        </CardContent>
      </Card>

      {/* Printer Selection */}
      <Card>
        <CardHeader>
          <CardTitle>Select Printer</CardTitle>
        </CardHeader>
        <CardContent>
          <PrinterSelect
            value={selectedPrinterName}
            onChange={(printerName) => {
              setSelectedPrinterName(printerName);
              // Printer selection is handled internally by PrinterSelect component
              // No need to save to localStorage - always query service fresh
            }}
            label="Select Label Printer"
            autoSelect={true}
          />
        </CardContent>
      </Card>

      {/* Items Table */}
      <Card>
        <CardHeader>
          <CardTitle className="flex items-center justify-between">
            <span className="flex items-center gap-2">
              <Package className="w-5 h-5" />
              Inventory Items ({reprintableItems.length})
            </span>
            <div className="flex items-center gap-2">
              <Checkbox
                checked={selectedItems.size === reprintableItems.length && reprintableItems.length > 0}
                onChange={(e) => handleSelectAll(e.target.checked)}
                disabled={reprintableItems.length === 0}
              />
              <span className="text-sm text-gray-600 dark:text-gray-400">
                Select All ({selectedItems.size} selected)
              </span>
            </div>
          </CardTitle>
        </CardHeader>
        <CardContent>
          {reprintableItems.length === 0 ? (
            <div className="text-center py-12 text-gray-500 dark:text-gray-400">
              <Package className="w-12 h-12 mx-auto mb-4 opacity-50" />
              <p>No reprintable items found</p>
              <p className="text-sm mt-2">
                All items from this {source === 'GRN' ? 'GRN' : 'Production Order'} have been sold.
              </p>
            </div>
          ) : (
            <>
              <div className="overflow-x-auto">
                <Table>
                  <TableHeader>
                    <TableRow>
                      <TableHead className="w-12">
                        <Checkbox
                          checked={selectedItems.size === reprintableItems.length && reprintableItems.length > 0}
                          onChange={(e) => handleSelectAll(e.target.checked)}
                        />
                      </TableHead>
                      <TableHead>Product</TableHead>
                      <TableHead>UID</TableHead>
                      <TableHead>Status</TableHead>
                      <TableHead>Created</TableHead>
                    </TableRow>
                  </TableHeader>
                  <TableBody>
                    {reprintableItems.map((item) => (
                      <TableRow key={item.id}>
                        <TableCell>
                          <Checkbox
                            checked={selectedItems.has(item.id)}
                            onChange={(e) => handleSelectItem(item.id, e.target.checked)}
                          />
                        </TableCell>
                        <TableCell className="font-medium">
                          {item.product?.name || 'Unknown Product'}
                        </TableCell>
                        <TableCell>
                          <code className="text-sm font-mono bg-gray-100 dark:bg-gray-800 px-2 py-1 rounded">
                            {item.uid}
                          </code>
                        </TableCell>
                        <TableCell>
                          <Badge variant={
                            item.status === 'IN_STOCK' ? 'success' :
                            item.status === 'RESERVED' ? 'warning' :
                            item.status === 'RETURNED' ? 'info' :
                            'secondary'
                          }>
                            {item.status}
                          </Badge>
                        </TableCell>
                        <TableCell>
                          <span className="text-sm text-gray-600 dark:text-gray-400">
                            {item.created_at
                              ? new Date(item.created_at).toLocaleDateString('en-US', {
                                  year: 'numeric',
                                  month: 'short',
                                  day: 'numeric',
                                })
                              : '-'}
                          </span>
                        </TableCell>
                      </TableRow>
                    ))}
                  </TableBody>
                </Table>
              </div>

              {/* Print Button */}
              <div className="mt-6 flex justify-end">
                <Button
                  variant="primary"
                  onClick={handlePrintSelected}
                  disabled={!selectedPrinterName || selectedItems.size === 0 || isPrinting}
                  loading={isPrinting}
                  className="flex items-center gap-2"
                >
                  <Printer className="w-4 h-4" />
                  Print {selectedItems.size} Selected Label{selectedItems.size !== 1 ? 's' : ''}
                </Button>
              </div>
            </>
          )}
        </CardContent>
      </Card>
    </div>
  );
}
