import { useMemo, useCallback } from 'react';
import type { FormScreenField } from '../../../api/types';
import { Select } from '../../reusable/Select';
import { Input } from '../../reusable/Input';
import { isCategoryColumn, isProductColumn, findColumn } from './gridUtils';

export interface OrderGridProps {
  label: string;
  columns: FormScreenField[];
  value: Record<string, unknown>[];
  onChange: (val: Record<string, unknown>[]) => void;
  totalBagsValue?: number;
  totalKgsValue?: number;
  showErrors?: boolean;
}

export function OrderGrid({
  label,
  columns,
  value = [],
  onChange,
  totalBagsValue,
  totalKgsValue,
  showErrors = false,
}: OrderGridProps) {
  const rows = value.length > 0 ? value : [{}];

  const catCol = useMemo(() => columns.find(c => isCategoryColumn(c.id, c.name)) || findColumn(columns, 'product_category', 'category'), [columns]);
  const prodNameCol = useMemo(() => columns.find(c => isProductColumn(c.id, c.name)), [columns]);
  const bagsCol = useMemo(() => findColumn(columns, 'bags', 'quantity', 'actual_potential', 'store_potential'), [columns]);

  const visibleColumns = useMemo(() => {
    const baseCols = (() => {
      if (columns.length === 0) {
        return [
          { id: 'product_category', name: 'Category', data_type: 'select' } as FormScreenField,
          { id: 'product_name', name: 'Product name', data_type: 'select' } as FormScreenField,
          { id: 'bags', name: 'Bags', data_type: 'number' } as FormScreenField,
        ];
      }
      const filtered = columns.filter((c) => {
        return isCategoryColumn(c.id, c.name) || isProductColumn(c.id, c.name) || c.id.includes('bags') || (c.name || '').toLowerCase().includes('bags');
      });
      if (filtered.length > 0) return filtered;
      
      return columns.filter((c) => {
        const idL = c.id.toLowerCase();
        const nL = (c.name || '').toLowerCase();
        return !idL.includes('sku') && !nL.includes('sku') && !idL.includes('br_code') && !nL.includes('br code') && !idL.includes('row_kgs');
      });
    })();

    return [
      ...baseCols,
      { id: '_row_total_kgs', name: 'Total (kgs)', data_type: 'readonly' } as FormScreenField,
    ];
  }, [columns]);

  const gridTemplateColumns = useMemo(() => {
    const numCols = visibleColumns.length;
    const actionCol = ' auto';
    if (numCols === 4) return `1.3fr 1.5fr 0.7fr 0.8fr${actionCol}`;
    if (numCols === 3) return `1.4fr 1.6fr 0.7fr${actionCol}`;
    if (numCols === 2) return `1.5fr 1.5fr${actionCol}`;
    return `repeat(${numCols}, minmax(0, 1fr))${actionCol}`;
  }, [visibleColumns]);

  const consolidateRows = useCallback((rowsList: Record<string, unknown>[]) => {
    const merged: Record<string, unknown>[] = [];
    const indexMap = new Map<string, number>();

    for (const r of rowsList) {
      const cat = String(r.category || r.product_category || (catCol ? r[catCol.id] : '') || '').trim().toLowerCase();
      const prod = String(r.productName || r.product_name || (prodNameCol ? r[prodNameCol.id] : '') || '').trim().toLowerCase();

      const bagsColId = bagsCol ? bagsCol.id : 'bags';
      const currentBags = Number(r[bagsColId] ?? r.bags ?? r.quantity ?? 0);

      if (cat && prod) {
        const key = `${cat}::${prod}`;
        if (indexMap.has(key) && currentBags > 0) {
          const targetIdx = indexMap.get(key)!;
          const existingRow = merged[targetIdx];

          const existingBags = Number(existingRow[bagsColId] ?? existingRow.bags ?? existingRow.quantity ?? 0);
          const addedBags = currentBags;
          const newBags = existingBags + addedBags;
          const skuVal = Number(existingRow.sku || r.sku || 0);

          const updatedRow: Record<string, unknown> = {
            ...existingRow,
            bags: newBags,
            quantity: newBags,
            row_kgs: skuVal * newBags,
          };
          if (bagsCol) updatedRow[bagsCol.id] = newBags;

          merged[targetIdx] = updatedRow;
          continue;
        } else if (!indexMap.has(key)) {
          indexMap.set(key, merged.length);
        }
      }

      merged.push(r);
    }

    return merged.length > 0 ? merged : [{}];
  }, [catCol, prodNameCol, bagsCol]);

  const isAnyRowIncomplete = useMemo(() => {
    return rows.some((r) => {
      const cat = String(r.category || r.product_category || (catCol ? r[catCol.id] : '') || '').trim();
      if (!cat) return true;

      if (prodNameCol) {
        const prod = String(r.productName || r.product_name || r[prodNameCol.id] || '').trim();
        if (!prod) return true;
      }

      if (bagsCol) {
        const bags = Number(r.bags || r.quantity || r[bagsCol.id] || 0);
        if (bags <= 0) return true;
      }
      
      return false;
    });
  }, [rows, catCol, prodNameCol, bagsCol]);

  const addRow = useCallback(() => {
    if (isAnyRowIncomplete) return;

    const consolidated = consolidateRows(rows);
    const cleanRows = consolidated.map((r) => {
      const clean: Record<string, unknown> = {};
      Object.keys(r).forEach((k) => {
        if (k !== '_row_total_kgs' && k !== 'row_kgs' && k !== 'row_total') {
          clean[k] = r[k];
        }
      });
      return clean;
    });

    onChange([...cleanRows, {}]);
  }, [rows, isAnyRowIncomplete, consolidateRows, onChange]);

  const removeRow = useCallback((idx: number) => {
    if (rows.length > 1) {
      const next = [...rows];
      next.splice(idx, 1);
      
      const cleanRows = next.map(r => {
        const clean: Record<string, unknown> = {};
        Object.keys(r).forEach(k => {
          if (k !== '_row_total_kgs' && k !== 'row_kgs' && k !== 'row_total') {
            clean[k] = r[k];
          }
        });
        return clean;
      });

      onChange(cleanRows);
    }
  }, [rows, onChange]);

  const categoriesList = useMemo(() => {
    if (catCol?.properties?.options && catCol.properties.options.length > 0) {
      return catCol.properties.options.map((o: any) => ({
        value: String(o.value ?? o.label),
        label: String(o.label ?? o.value),
      }));
    }
    return [];
  }, [catCol]);

  const getProductsForCategory = useCallback((selectedCat?: string) => {
    let allOpts: { value: string; label: string; rawCat?: string; raw?: any }[] = [];

    if (prodNameCol?.properties?.options && prodNameCol.properties.options.length > 0) {
      allOpts = prodNameCol.properties.options.map((o: any) => {
        const val = String(o.value ?? o.label ?? '');
        const label = String(o.label ?? o.value ?? '');
        const rawCat = o._raw?.product_category || o._raw?.cat || o._raw?.category;
        return { value: val, label, rawCat, raw: o._raw };
      });

      if (selectedCat) {
        allOpts = allOpts.filter((o) => {
          if (o.rawCat) {
            return String(o.rawCat).trim().toLowerCase() === String(selectedCat).trim().toLowerCase();
          }
          return o.label.toLowerCase().startsWith(String(selectedCat).toLowerCase());
        });
      }
    }

    return allOpts;
  }, [prodNameCol]);

  const updateRowField = useCallback((rowIdx: number, fieldId: string, val: unknown) => {
    const next = rows.map((r) => ({ ...r }));
    let row = { ...next[rowIdx] };

    const colDef = columns.find((c) => c.id === fieldId) || visibleColumns.find((c) => c.id === fieldId);
    const colName = colDef?.name || '';

    const isCatField = isCategoryColumn(fieldId, colName);
    const isProdField = isProductColumn(fieldId, colName);
    const isBagsField = colDef?.data_type === 'number' || fieldId.includes('bags') || fieldId.includes('quantity') || colName.toLowerCase().includes('bags');

    if (isCatField) {
      const catVal = String(val ?? '');
      row[fieldId] = catVal;
      row['category'] = catVal;
      row['product_category'] = catVal;

      const pColId = prodNameCol?.id || 'product_name';
      row[pColId] = '';
      row['product_name'] = '';
      row['productName'] = '';
      row['sku'] = '';
      row['br_code'] = '';
      row['br'] = '';
      row['sku_code'] = '';
      row['skucode'] = '';
      row['bags'] = '';
      row['quantity'] = '';
      if (bagsCol) row[bagsCol.id] = '';
      row['row_kgs'] = 0;
    } else if (isProdField) {
      const currentCat = String(row['category'] || row['product_category'] || (catCol ? row[catCol.id] : '') || '');
      const prodOptions = getProductsForCategory(currentCat);

      const matchedOpt = prodOptions.find(
        (o) => o.value === String(val) || o.label === String(val) || o.label.toLowerCase() === String(val).toLowerCase()
      );

      const selectedName = matchedOpt?.label || String(val);
      const sku = matchedOpt?.raw?.sku || '';
      const br = matchedOpt?.raw?.br_code || matchedOpt?.raw?.br || matchedOpt?.raw?.brcode || matchedOpt?.raw?.brand_code || '';
      const skucode = matchedOpt?.raw?.sku_code || matchedOpt?.raw?.skucode || '';
      const cat = matchedOpt?.rawCat || matchedOpt?.raw?.product_category || currentCat;

      const setVal = matchedOpt?.value || String(val);
      row[fieldId] = setVal;
      row['product_name'] = selectedName;
      row['productName'] = selectedName;
      if (prodNameCol) row[prodNameCol.id] = setVal;

      row['sku'] = sku;
      const skuCol = findColumn(columns, 'sku');
      if (skuCol) row[skuCol.id] = sku;

      row['br'] = br;
      row['br_code'] = br;
      const brCol = findColumn(columns, 'br_code', 'br');
      if (brCol) row[brCol.id] = br;

      row['skucode'] = skucode;
      row['sku_code'] = skucode;
      const skuCodeCol = findColumn(columns, 'sku_code', 'skucode');
      if (skuCodeCol) row[skuCodeCol.id] = skucode;

      if (cat) {
        row['category'] = cat;
        row['product_category'] = cat;
        if (catCol) row[catCol.id] = cat;
      }

      const bagsVal = Number(row.bags ?? row.quantity ?? (bagsCol ? row[bagsCol.id] : 0)) || 0;
      row['row_kgs'] = Number(sku || 0) * bagsVal;
    } else if (isBagsField) {
      const parsedVal = val !== '' && val !== null && val !== undefined ? val : '';
      const numericVal = Number(val) || 0;

      row[fieldId] = parsedVal;
      row['bags'] = parsedVal;
      row['quantity'] = parsedVal;
      if (bagsCol) row[bagsCol.id] = parsedVal;

      const skuVal = Number(row.sku || 0);
      row['row_kgs'] = skuVal * numericVal;
    } else {
      row[fieldId] = val;
    }

    next[rowIdx] = row;

    const cleanRows = next.map((r) => {
      const clean: Record<string, unknown> = {};
      Object.keys(r).forEach((k) => {
        if (k !== '_row_total_kgs' && k !== 'row_kgs' && k !== 'row_total') {
          clean[k] = r[k];
        }
      });
      return clean;
    });

    onChange(cleanRows);
  }, [rows, columns, visibleColumns, prodNameCol, catCol, bagsCol, getProductsForCategory, onChange]);

  const { calculatedBags, calculatedKgs } = useMemo(() => {
    let bagsAcc = 0;
    let kgsAcc = 0;
    for (const r of rows) {
      const b = Number(r.bags ?? r.quantity ?? (bagsCol ? r[bagsCol.id] : 0)) || 0;
      const sku = Number(r.sku) || 0;
      bagsAcc += b;
      kgsAcc += b * sku;
    }
    return { calculatedBags: Math.round(bagsAcc), calculatedKgs: Math.round(kgsAcc) };
  }, [rows, bagsCol]);

  const displayTotalBags = totalBagsValue !== undefined ? totalBagsValue : calculatedBags;
  const displayTotalKgs = totalKgsValue !== undefined ? totalKgsValue : calculatedKgs;

  return (
    <div className="max-w-full bg-[var(--tiles-card-bg)] rounded-xl border border-border-default p-6 space-y-6 shadow-sm font-sans">
      <div className="flex items-center justify-between">
        <p className="text-sm font-bold text-slate-700 uppercase tracking-wide">
          {label || 'Order details'}
        </p>
      </div>

      <div className="border-t border-border-subtle pt-4">
        <div className="grid gap-3 px-1 pb-2 text-xs font-bold text-muted uppercase tracking-wider" style={{ gridTemplateColumns }}>
          {visibleColumns.map((col) => (
            <span key={col.id}>{col.name}</span>
          ))}
          <span />
        </div>

        <div className="space-y-3">
          {rows.map((row, rowIdx) => {
            const currentCatVal = String(row.category ?? row.product_category ?? (catCol ? row[catCol.id] : '') ?? '');
            const currentProdVal = String(row[prodNameCol?.id || 'product_name'] ?? row.product_name ?? row.productName ?? '');
            const currentBagsVal = row.bags ?? row.quantity ?? (bagsCol ? row[bagsCol.id] : '') ?? '';

            const prodOptions = getProductsForCategory(currentCatVal);
            const isCategorySelected = Boolean(currentCatVal.trim());

            const skuNum = Number(row.sku) || 0;
            const bagsNum = Number(currentBagsVal) || 0;
            const computedRowKgs = skuNum * bagsNum;

            const isMissingProd = isCategorySelected && !currentProdVal.trim();
            const prodError = showErrors && isMissingProd ? 'Required' : undefined;

            const isMissingBags = isCategorySelected && (!currentBagsVal || Number(currentBagsVal) <= 0);
            const bagsError = showErrors && isMissingBags ? 'Required' : undefined;

            return (
              <div key={rowIdx}>
                <div className="grid gap-3 items-center" style={{ gridTemplateColumns }}>
                  {visibleColumns.map((col) => {
                    const fieldId = col.id;

                    if (fieldId === '_row_total_kgs') {
                      return (
                        <Input
                          key={fieldId}
                          disabled
                          value={computedRowKgs > 0 ? `${computedRowKgs.toLocaleString()} kgs` : '0 kgs'}
                          className="w-full font-semibold text-slate-700 bg-slate-50 border-slate-200"
                        />
                      );
                    }

                    const isCat = isCategoryColumn(fieldId, col.name);
                    const isProd = isProductColumn(fieldId, col.name);
                    const isBagsOrNum = col.data_type === 'number' || fieldId.includes('bags') || fieldId.includes('quantity') || col.name?.toLowerCase().includes('bags');

                    if (isCat) {
                      return (
                        <Select
                          key={fieldId}
                          value={currentCatVal}
                          onChange={(e) => updateRowField(rowIdx, fieldId, e.target.value)}
                          options={[{ value: '', label: 'Category' }, ...categoriesList]}
                          className="w-full"
                        />
                      );
                    }

                    if (isProd) {
                      return (
                        <Select
                          key={fieldId}
                          value={currentProdVal}
                          onChange={(e) => updateRowField(rowIdx, fieldId, e.target.value)}
                          disabled={!isCategorySelected && categoriesList.length > 0}
                          options={[
                            { value: '', label: isCategorySelected || categoriesList.length === 0 ? 'Select product' : 'Select category first' },
                            ...prodOptions
                          ]}
                          error={prodError}
                          className="w-full"
                        />
                      );
                    }

                    if (isBagsOrNum) {
                      const isMainBagsCol = bagsCol?.id === fieldId || fieldId === 'bags' || fieldId === 'quantity';
                      const numVal = isMainBagsCol ? currentBagsVal : row[fieldId];
                      return (
                        <Input
                          key={fieldId}
                          type="number"
                          min={isMainBagsCol ? "1" : undefined}
                          value={numVal !== undefined && numVal !== null ? String(numVal) : ''}
                          onChange={(e) => updateRowField(rowIdx, fieldId, e.target.value)}
                          placeholder={isMainBagsCol && isCategorySelected ? 'Bags' : '0'}
                          error={isMainBagsCol ? bagsError : undefined}
                          className="w-full"
                        />
                      );
                    }

                    if (col.data_type === 'select' || col.data_type === 'multiselect') {
                      const opts = col.properties?.options || [];
                      return (
                        <Select
                          key={fieldId}
                          value={String(row[fieldId] ?? '')}
                          onChange={(e) => updateRowField(rowIdx, fieldId, e.target.value)}
                          options={[{ value: '', label: 'Select...' }, ...opts.map((o: any) => ({ value: String(o.value), label: o.label }))]}
                          className="w-full"
                        />
                      );
                    }

                    return (
                      <Input
                        key={fieldId}
                        type="text"
                        value={String(row[fieldId] ?? '')}
                        onChange={(e) => updateRowField(rowIdx, fieldId, e.target.value)}
                        className="w-full"
                      />
                    );
                  })}

                  <button
                    type="button"
                    onClick={() => removeRow(rowIdx)}
                    aria-label="Remove product"
                    disabled={rows.length === 1}
                    className="h-[42px] w-[42px] flex items-center justify-center rounded-md border border-border-default text-slate-500 hover:bg-slate-50 hover:border-ruby-300 hover:text-ruby-600 disabled:opacity-30 disabled:hover:bg-transparent disabled:hover:text-slate-500 transition-colors shrink-0"
                  >
                    ✕
                  </button>
                </div>
              </div>
            );
          })}
        </div>

        <div className="pt-2 flex justify-end">
          <button
            type="button"
            onClick={addRow}
            disabled={isAnyRowIncomplete}
            className="text-xs px-3.5 py-2 rounded-md bg-slate-900 text-white hover:bg-slate-800 font-semibold transition-all shadow-sm flex items-center gap-1.5 disabled:opacity-40 disabled:cursor-not-allowed disabled:hover:bg-slate-900"
          >
            + Add product
          </button>
        </div>

        {bagsCol && (
          <div className="border-t border-border-subtle pt-3 mt-4">
            <div className="grid gap-3 items-center" style={{ gridTemplateColumns }}>
              {visibleColumns.map((col, idx) => {
                const fieldId = col.id;
                const isBagsOrNum = col.data_type === 'number' || fieldId.includes('bags') || fieldId.includes('quantity') || col.name?.toLowerCase().includes('bags');

                if (isBagsOrNum) {
                  return (
                    <Input
                      key={fieldId}
                      disabled
                      value={displayTotalBags.toLocaleString()}
                      className="w-full font-bold text-center text-slate-800 bg-slate-100 border-slate-200"
                    />
                  );
                }

                if (fieldId === '_row_total_kgs') {
                  return (
                    <Input
                      key={fieldId}
                      disabled
                      value={`${displayTotalKgs.toLocaleString()} kgs`}
                      className="w-full font-bold text-center text-slate-800 bg-slate-100 border-slate-200"
                    />
                  );
                }

                if (idx === 0) {
                  return <div key={col.id} className="flex items-center text-xs font-bold text-slate-500 uppercase tracking-wider px-1">Total</div>;
                }

                return <div key={col.id} />;
              })}
              <div className="w-[42px]" />
            </div>
          </div>
        )}
      </div>
    </div>
  );
}
