import { DataTable } from '@/components/ui';
import { PlusIcon, TrashIcon } from '@heroicons/react/24/outline';
import type { ColumnDef, Row } from '@tanstack/react-table';
import { useCallback, useMemo, useState } from 'react';
import { useExchanges } from '../hooks/useExchanges';
import type { AddProviderMappingDialogState, DeleteDialogState, EditingCell, Exchange } from '../types';
import { formatDate, formatProviderMapping, getProviderMappingColor, sortProviderMappings } from '../utils/formatters';
import { AddProviderMappingDialog } from './AddProviderMappingDialog';
import { DeleteExchangeDialog } from './DeleteExchangeDialog';

export function ExchangesTable() {
  const { 
    exchanges, 
    loading, 
    error, 
    updateExchange,
    updateProviderMapping,
    createProviderMapping,
    refetch 
  } = useExchanges();

  const [editingCell, setEditingCell] = useState<EditingCell | null>(null);
  const [editValue, setEditValue] = useState('');
  const [addProviderDialog, setAddProviderDialog] = useState<AddProviderMappingDialogState | null>(null);
  const [deleteDialog, setDeleteDialog] = useState<DeleteDialogState | null>(null);

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

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

  const handleAddProviderMapping = useCallback(async (exchangeId: string, exchangeName: string) => {
    setAddProviderDialog({ exchangeId, exchangeName });
  }, []);

  const handleDeleteExchange = useCallback((exchangeId: string, exchangeName: string, providerMappingCount: number) => {
    setDeleteDialog({ exchangeId, exchangeName, providerMappingCount });
  }, []);

  const handleConfirmDelete = useCallback(async (exchangeId: string) => {
    const success = await updateExchange(exchangeId, { visible: false });
    if (success) {
      refetch();
    }
    return success;
  }, [updateExchange, refetch]);

  const handleToggleProviderMapping = useCallback(
    async (mappingId: string, currentStatus: boolean) => {
      const success = await updateProviderMapping(mappingId, { active: !currentStatus });
      if (success) {
        // Refresh the main table data to get updated counts and mappings
        refetch();
      }
    },
    [updateProviderMapping, refetch]
  );

  const handleRowExpand = useCallback(
    (_row: Row<Exchange>) => {
      // Row expansion is now handled automatically by TanStack Table
      // No need to fetch data since all mappings are already loaded
    },
    []
  );

  const columns = useMemo<ColumnDef<Exchange>[]>(() => {
    return [
      {
        id: 'expander',
        header: '',
        cell: ({ row }) => {
          return row.getCanExpand() ? (
            <button
              onClick={() => {
                row.getToggleExpandedHandler()();
                handleRowExpand(row);
              }}
              className="text-text-secondary hover:text-text-primary transition-colors w-6 h-6 flex items-center justify-center"
            >
              {row.getIsExpanded() ? '▼' : '▶'}
            </button>
          ) : null;
        },
        size: 40,
        enableResizing: false,
        disableTooltip: true,
      },
      {
        id: 'code',
        header: 'Code',
        accessorKey: 'code',
        size: 120,
        cell: ({ getValue, row, cell: _cell }) => {
          const isEditing =
            editingCell?.id === row.original.id && editingCell?.field === 'code';

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

          return (
            <div
              className="cursor-pointer hover:bg-surface-secondary rounded px-2 py-1 transition-colors text-sm font-mono font-medium truncate overflow-hidden text-ellipsis whitespace-nowrap"
              onClick={() => {
                setEditingCell({ id: row.original.id, field: 'code' });
                setEditValue(getValue() as string);
              }}
            >
              {getValue() as string}
            </div>
          );
        },
      },
      {
        id: 'name',
        header: 'Name',
        accessorKey: 'name',
        size: 250,
        cell: ({ getValue, row, cell: _cell }) => {
          const isEditing =
            editingCell?.id === row.original.id && editingCell?.field === 'name';

          if (isEditing) {
            return (
              <input
                type="text"
                value={editValue}
                onChange={e => setEditValue(e.target.value)}
                onBlur={() => handleCellEdit(row.original.id, 'name', editValue)}
                onKeyDown={e => {
                  if (e.key === 'Enter') {
                    handleCellEdit(row.original.id, 'name', 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 truncate overflow-hidden text-ellipsis whitespace-nowrap"
              onClick={() => {
                setEditingCell({ id: row.original.id, field: 'name' });
                setEditValue(getValue() as string);
              }}
            >
              {getValue() as string}
            </div>
          );
        },
      },
      {
        id: 'country',
        header: 'Country',
        accessorKey: 'country',
        size: 80,
        cell: ({ getValue }) => (
          <span className="text-text-secondary text-sm block truncate">{getValue() as string}</span>
        ),
      },
      {
        id: 'currency',
        header: 'Currency',
        accessorKey: 'currency',
        size: 80,
        cell: ({ getValue }) => (
          <span className="font-mono text-text-secondary text-sm block truncate">
            {getValue() as string}
          </span>
        ),
      },
      {
        id: 'active',
        header: 'Active',
        accessorKey: 'active',
        size: 80,
        disableTooltip: true,
        cell: ({ getValue, row }) => {
          const isActive = getValue() as boolean;
          return (
            <label className="relative inline-flex items-center cursor-pointer">
              <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: 'provider_mappings',
        header: 'Provider Mappings',
        accessorKey: 'provider_mapping_count',
        size: 180,
        disableTooltip: true,
        cell: ({ getValue, row }) => {
          const totalMappings = parseInt(getValue() as string) || 0;
          const activeMappings = parseInt(row.original.active_mapping_count) || 0;
          // const _verifiedMappings = parseInt(row.original.verified_mapping_count) || 0;
          
          // Get provider mappings directly from the exchange data
          const mappings = row.original.provider_mappings || [];
          const sortedMappings = sortProviderMappings(mappings);

          return (
            <div className="flex flex-col gap-1">
              <div className="text-sm">
                <span className="text-text-primary font-medium">{totalMappings}</span>
                <span className="text-text-muted"> total</span>
                {activeMappings > 0 && (
                  <span className="ml-2 text-green-400 text-xs">
                    {activeMappings} active
                  </span>
                )}
              </div>
              {mappings.length > 0 ? (
                <div className="flex flex-wrap gap-1 text-xs">
                  {sortedMappings.slice(0, 3).map((mapping, index) => (
                    <span key={index} className={getProviderMappingColor(mapping)}>
                      {formatProviderMapping(mapping)}
                    </span>
                  ))}
                  {sortedMappings.length > 3 && (
                    <span className="text-text-muted">+{sortedMappings.length - 3} more</span>
                  )}
                </div>
              ) : (
                <div className="text-xs text-text-muted">No mappings</div>
              )}
            </div>
          );
        },
      },
      {
        id: 'actions',
        header: 'Actions',
        size: 160,
        disableTooltip: true,
        cell: ({ row }) => (
          <div className="flex gap-1">
            <button
              onClick={() => handleAddProviderMapping(row.original.id, row.original.name)}
              className="inline-flex items-center gap-1 px-3 py-1.5 bg-primary-500/20 text-primary-400 rounded text-xs hover:bg-primary-500/30 transition-colors whitespace-nowrap"
              title="Add Provider Mapping"
            >
              <PlusIcon className="h-3 w-3" />
              Add
            </button>
            <button
              onClick={() => handleDeleteExchange(
                row.original.id, 
                row.original.name, 
                parseInt(row.original.provider_mapping_count) || 0
              )}
              className="inline-flex items-center gap-1 px-3 py-1.5 bg-danger/20 text-danger rounded text-xs hover:bg-danger/30 transition-colors whitespace-nowrap"
              title="Delete Exchange"
            >
              <TrashIcon className="h-3 w-3" />
              Delete
            </button>
          </div>
        ),
      },
      {
        id: 'updated_at',
        header: 'Last Updated',
        accessorKey: 'updated_at',
        size: 120,
        cell: ({ getValue }) => (
          <span className="text-xs text-text-muted">
            {formatDate(getValue() as string)}
          </span>
        ),
      },
    ];
  }, [
    editingCell,
    editValue,
    handleCellEdit,
    handleToggleActive,
    handleAddProviderMapping,
    handleDeleteExchange,
    handleRowExpand,
  ]);

  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 web-api service is running on localhost:2003
        </p>
      </div>
    );
  }

  const renderSubComponent = ({ row }: { row: Row<Exchange> }) => {
    const exchange = row.original as Exchange;
    const mappings = exchange.provider_mappings || [];
    
    if (mappings.length === 0) {
      return (
        <div className="p-4 text-center text-text-muted">
          <div className="text-sm">No provider mappings found for this exchange.</div>
          <button
            onClick={() => handleAddProviderMapping(exchange.id, exchange.name)}
            className="mt-2 text-primary-400 hover:text-primary-300 text-sm underline"
          >
            Add the first provider mapping
          </button>
        </div>
      );
    }

    return (
      <div className="p-4 bg-surface-secondary/50">
        <h4 className="text-sm font-medium text-text-primary mb-3">Provider Mappings</h4>
        <div className="space-y-2">
          {mappings.map((mapping) => (
            <div key={mapping.id} className="flex items-center justify-between p-3 bg-surface rounded border border-border">
              <div className="flex-1">
                <div className="flex items-center gap-3">
                  <span className="font-mono text-xs bg-primary-500/20 text-primary-400 px-2 py-1 rounded">
                    {mapping.provider.toUpperCase()}
                  </span>
                  <span className="font-medium text-text-primary">
                    {mapping.provider_exchange_code}
                  </span>
                  <span className="text-text-secondary">
                    {mapping.provider_exchange_name}
                  </span>
                  {mapping.country_code && (
                    <span className="text-xs text-text-muted">
                      {mapping.country_code}
                    </span>
                  )}
                </div>
                <div className="flex items-center gap-4 mt-1 text-xs text-text-muted">
                  <span>Confidence: {mapping.confidence}</span>
                  <span>Created: {formatDate(mapping.created_at)}</span>
                  {mapping.auto_mapped && <span className="text-yellow-400">Auto-mapped</span>}
                </div>
              </div>
              <div className="flex items-center gap-2">
                <div className="flex items-center gap-1">
                  {mapping.verified && (
                    <span className="text-blue-400" title="Verified">
                      ✓
                    </span>
                  )}
                  <label className="relative inline-flex items-center cursor-pointer">
                    <input
                      type="checkbox"
                      checked={mapping.active}
                      onChange={() => handleToggleProviderMapping(mapping.id, mapping.active)}
                      className="sr-only peer"
                    />
                    <div className="w-6 h-3 bg-surface-secondary peer-focus:outline-none peer-focus:ring-1 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-[1px] after:left-[1px] after:bg-white after:rounded-full after:h-2.5 after:w-2.5 after:transition-all peer-checked:bg-primary-500"></div>
                  </label>
                </div>
              </div>
            </div>
          ))}
        </div>
      </div>
    );
  };

  return (
    <>
      <DataTable
        data={exchanges || []}
        columns={columns}
        loading={loading}
        getRowCanExpand={() => true}
        renderSubComponent={renderSubComponent}
      />

      {addProviderDialog && (
        <AddProviderMappingDialog
          isOpen={true}
          exchangeId={addProviderDialog.exchangeId}
          exchangeName={addProviderDialog.exchangeName}
          onClose={() => setAddProviderDialog(null)}
          onCreateMapping={async (mappingRequest) => {
            const result = await createProviderMapping(mappingRequest);
            if (result) {
              setAddProviderDialog(null);
              refetch();
            }
          }}
        />
      )}

      {deleteDialog && (
        <DeleteExchangeDialog
          isOpen={true}
          exchangeId={deleteDialog.exchangeId}
          exchangeName={deleteDialog.exchangeName}
          providerMappingCount={deleteDialog.providerMappingCount}
          onClose={() => setDeleteDialog(null)}
          onConfirmDelete={handleConfirmDelete}
        />
      )}
    </>
  );
}
