import { DataTable } from '@/components/ui';
import { PlusIcon, XMarkIcon } from '@heroicons/react/24/outline';
import { ColumnDef } from '@tanstack/react-table';
import { useCallback, useMemo, useState } from 'react';
import { useExchanges } from '../hooks/useExchanges';
import { Exchange, SourceMapping } from '../types';
import { AddSourceDialog } from './AddSourceDialog';

export function ExchangesTable() {
  const { exchanges, loading, error, updateExchange, addSource, removeSource } = useExchanges();
  const [editingCell, setEditingCell] = useState<{ id: string; field: string } | null>(null);
  const [editValue, setEditValue] = useState('');
  const [addSourceDialog, setAddSourceDialog] = useState<{
    id: string;
    exchangeName: string;
  } | null>(null);

  const handleCellEdit = useCallback(
    async (id: string, field: string, value: string) => {
      if (field === 'shortName') {
        await updateExchange(id, { shortName: value });
      }
      setEditingCell(null);
      setEditValue('');
    },
    [updateExchange]
  );

  const handleToggleActive = useCallback(
    async (id: string, currentStatus: boolean) => {
      await updateExchange(id, { active: !currentStatus });
    },
    [updateExchange]
  );

  const handleAddSource = useCallback(async (id: string, exchangeName: string) => {
    setAddSourceDialog({ id, exchangeName });
  }, []);

  const handleRemoveSource = useCallback(
    async (exchangeId: string, sourceName: string) => {
      if (confirm(`Are you sure you want to remove the ${sourceName} source?`)) {
        await removeSource(exchangeId, sourceName);
      }
    },
    [removeSource]
  );

  const columns = useMemo<ColumnDef<Exchange>[]>(() => {
    return [
      {
        id: 'masterExchangeId',
        header: 'Master ID',
        accessorKey: 'masterExchangeId',
        size: 50,
        enableResizing: false,
        cell: ({ getValue, cell }) => (
          <span
            className="font-mono text-primary-400 text-xs"
            style={{ width: cell.column.getSize() }}
          >
            {getValue() as string}
          </span>
        ),
      },
      {
        id: 'shortName',
        header: 'Short Name',
        accessorKey: 'shortName',
        size: 50,
        enableResizing: false,
        cell: ({ getValue, row, cell }) => {
          const isEditing =
            editingCell?.id === row.original._id && editingCell?.field === 'shortName';

          if (isEditing) {
            return (
              <input
                type="text"
                style={{ width: cell.column.getSize() }}
                value={editValue}
                onChange={e => setEditValue(e.target.value)}
                onBlur={() => handleCellEdit(row.original._id, 'shortName', editValue)}
                onKeyDown={e => {
                  if (e.key === 'Enter') {
                    handleCellEdit(row.original._id, 'shortName', editValue);
                  } else if (e.key === 'Escape') {
                    setEditingCell(null);
                    setEditValue('');
                  }
                }}
                className="w-full bg-surface border border-border rounded px-2 py-1 text-sm"
                autoFocus
              />
            );
          }

          return (
            <div
              className="cursor-pointer hover:bg-surface-secondary rounded px-2 py-1 transition-colors text-sm"
              onClick={() => {
                setEditingCell({ id: row.original._id, field: 'shortName' });
                setEditValue(getValue() as string);
              }}
            >
              {getValue() as string}
            </div>
          );
        },
      },
      {
        id: 'officialName',
        header: 'Official Name',
        accessorKey: 'officialName',
        size: 150,
        maxSize: 150,
        enableResizing: true,
        cell: ({ getValue, cell }) => (
          <span
            className="text-text-primary text-sm truncate block"
            title={getValue() as string}
            style={{ width: cell.column.getSize() }}
          >
            {getValue() as string}
          </span>
        ),
      },
      {
        id: 'country',
        header: 'Country',
        accessorKey: 'country',
        size: 40,
        maxSize: 40,
        cell: ({ getValue }) => (
          <span className="text-text-secondary text-sm">{getValue() as string}</span>
        ),
      },
      {
        id: 'currency',
        header: 'Currency',
        accessorKey: 'currency',
        size: 40,
        cell: ({ getValue, cell }) => (
          <span
            className="font-mono text-text-secondary text-sm"
            style={{ width: cell.column.getSize() }}
          >
            {getValue() as string}
          </span>
        ),
      },
      {
        id: 'active',
        header: 'Active',
        accessorKey: 'active',
        size: 80,
        maxSize: 80,
        cell: ({ getValue, row, cell }) => {
          const isActive = getValue() as boolean;
          return (
            <label
              className="relative inline-flex items-center cursor-pointer"
              style={{ width: cell.column.getSize() }}
            >
              <input
                type="checkbox"
                checked={isActive}
                onChange={() => handleToggleActive(row.original._id, isActive)}
                className="sr-only peer"
              />
              <div className="w-9 h-5 bg-surface-secondary peer-focus:outline-none peer-focus:ring-2 peer-focus:ring-primary-500 rounded-full peer peer-checked:after:translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-[2px] after:left-[2px] after:bg-white after:rounded-full after:h-4 after:w-4 after:transition-all peer-checked:bg-primary-500"></div>
            </label>
          );
        },
      },
      {
        id: 'sources',
        header: 'Sources',
        accessorKey: 'sourceMappings',
        minSize: 400,
        maxSize: 400,
        size: 400,
        enableResizing: true,
        cell: ({ getValue, row, cell }) => {
          const sourceMappings = getValue() as Record<string, SourceMapping>;
          const sources = Object.keys(sourceMappings);

          return (
            <div className="flex flex-wrap gap-1" style={{ width: cell.column.getSize() }}>
              {sources.map(source => {
                // The source key is already in format "source_sourcecode" from the storage
                const displayText = source.toUpperCase();

                return (
                  <span
                    key={source}
                    className="inline-flex items-center gap-1 px-2 py-1 bg-surface-secondary rounded text-xs"
                  >
                    {displayText}
                    <button
                      onClick={() => handleRemoveSource(row.original._id, source)}
                      className="text-danger hover:text-danger/80 transition-colors"
                    >
                      <XMarkIcon className="h-3 w-3" />
                    </button>
                  </span>
                );
              })}
              <button
                onClick={() => handleAddSource(row.original._id, row.original.officialName)}
                className="inline-flex items-center justify-center w-6 h-6 bg-primary-500/20 text-primary-400 rounded text-xs hover:bg-primary-500/30 transition-colors"
                title="Add Source"
              >
                <PlusIcon className="h-3 w-3" />
              </button>
            </div>
          );
        },
      },
      {
        id: 'updated_at',
        header: 'Last Updated',
        accessorKey: 'updated_at',
        size: 150,
        maxSize: 150,
        cell: ({ getValue }) => (
          <span className="text-xs text-text-muted">
            {new Date(getValue() as string).toLocaleDateString()}
          </span>
        ),
      },
    ];
  }, [
    editingCell,
    editValue,
    handleCellEdit,
    handleRemoveSource,
    handleToggleActive,
    handleAddSource,
  ]);

  if (error) {
    return (
      <div className="bg-danger/10 border border-danger/20 rounded-lg p-4">
        <h3 className="text-danger font-medium mb-2">Error Loading Exchanges</h3>
        <p className="text-text-secondary text-sm">{error}</p>
        <p className="text-text-muted text-xs mt-2">
          Make sure the data-service is running on localhost:2001
        </p>
      </div>
    );
  }

  return (
    <>
      <DataTable
        data={exchanges || []}
        columns={columns}
        loading={loading}
        className="rounded-lg border border-border"
      />

      {addSourceDialog && (
        <AddSourceDialog
          isOpen={true}
          exchangeId={addSourceDialog.id}
          exchangeName={addSourceDialog.exchangeName}
          onClose={() => setAddSourceDialog(null)}
          onAddSource={async (sourceRequest: {
            source: string;
            source_code: string;
            mapping: { id: string; name: string; code: string; aliases: string[] };
          }) => {
            const success = await addSource(addSourceDialog.id, sourceRequest);
            if (success) {
              setAddSourceDialog(null);
            }
          }}
        />
      )}
    </>
  );
}
