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

export function ExchangesTable() {
  const { 
    exchanges, 
    loading, 
    error, 
    updateExchange, 
    fetchExchangeDetails,
    fetchProviderMappings,
    updateProviderMapping,
    createProviderMapping,
    refetch 
  } = useExchanges();
  const [editingCell, setEditingCell] = useState<{ id: string; field: string } | null>(null);
  const [editValue, setEditValue] = useState('');
  const [addProviderDialog, setAddProviderDialog] = useState<{
    exchangeId: string;
    exchangeName: string;
  } | null>(null);
  const [expandedRows, setExpandedRows] = useState<Set<string>>(new Set());
  const [expandedRowData, setExpandedRowData] = useState<Record<string, ProviderMapping[]>>({});

  const handleCellEdit = useCallback(
    async (id: string, field: string, value: string) => {
      if (field === 'name') {
        await updateExchange(id, { name: 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 handleToggleProviderMapping = useCallback(
    async (mappingId: string, currentStatus: boolean) => {
      const success = await updateProviderMapping(mappingId, { active: !currentStatus });
      if (success) {
        refetch();
      }
    },
    [updateProviderMapping, refetch]
  );

  const handleToggleExpandRow = useCallback(async (rowId: string) => {
    setExpandedRows(prev => {
      const next = new Set(prev);
      if (next.has(rowId)) {
        next.delete(rowId);
      } else {
        next.add(rowId);
        // Load provider mappings for this exchange
        if (!expandedRowData[rowId]) {
          fetchExchangeDetails(rowId).then(details => {
            if (details) {
              setExpandedRowData(prev => ({
                ...prev,
                [rowId]: details.provider_mappings
              }));
            }
          });
        }
      }
      return next;
    });
  }, [fetchExchangeDetails, expandedRowData]);

  const columns = useMemo<ColumnDef<Exchange>[]>(() => {
    return [
      {
        id: 'expand',
        header: '',
        size: 30,
        enableResizing: false,
        cell: ({ row }) => {
          const isExpanded = expandedRows.has(row.original.id);
          return (
            <button
              onClick={() => handleToggleExpandRow(row.original.id)}
              className="text-text-secondary hover:text-text-primary transition-colors"
            >
              {isExpanded ? '▼' : '▶'}
            </button>
          );
        },
      },
      {
        id: 'id',
        header: 'ID',
        accessorKey: 'id',
        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: 'code',
        header: 'Code',
        accessorKey: 'code',
        size: 80,
        enableResizing: false,
        cell: ({ getValue, cell }) => (
          <span
            className="font-mono text-text-primary text-sm font-medium"
            style={{ width: cell.column.getSize() }}
          >
            {getValue() as string}
          </span>
        ),
      },
      {
        id: 'name',
        header: 'Name',
        accessorKey: 'name',
        size: 200,
        maxSize: 300,
        enableResizing: true,
        cell: ({ getValue, row, cell }) => {
          const isEditing =
            editingCell?.id === row.original.id && editingCell?.field === 'name';

          if (isEditing) {
            return (
              <input
                type="text"
                style={{ width: cell.column.getSize() }}
                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"
              onClick={() => {
                setEditingCell({ id: row.original.id, field: 'name' });
                setEditValue(getValue() as string);
              }}
            >
              {getValue() as string}
            </div>
          );
        },
      },
      {
        id: 'country',
        header: 'Country',
        accessorKey: 'country',
        size: 80,
        maxSize: 80,
        cell: ({ getValue }) => (
          <span className="text-text-secondary text-sm">{getValue() as string}</span>
        ),
      },
      {
        id: 'currency',
        header: 'Currency',
        accessorKey: 'currency',
        size: 70,
        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: 'provider_mappings',
        header: 'Provider Mappings',
        accessorKey: 'provider_mapping_count',
        size: 150,
        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;
          const providers = row.original.providers;

          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>
              </div>
              <div className="flex gap-2 text-xs">
                <span className="text-green-400">
                  <CheckIcon className="h-3 w-3 inline mr-1" />
                  {activeMappings} active
                </span>
                <span className="text-blue-400">
                  ✓ {verifiedMappings} verified
                </span>
              </div>
              {providers && (
                <div className="text-xs text-text-muted truncate" title={providers}>
                  {providers}
                </div>
              )}
            </div>
          );
        },
      },
      {
        id: 'actions',
        header: 'Actions',
        size: 100,
        cell: ({ row }) => (
          <button
            onClick={() => handleAddProviderMapping(row.original.id, row.original.name)}
            className="inline-flex items-center gap-1 px-2 py-1 bg-primary-500/20 text-primary-400 rounded text-xs hover:bg-primary-500/30 transition-colors"
            title="Add Provider Mapping"
          >
            <PlusIcon className="h-3 w-3" />
            Add Mapping
          </button>
        ),
      },
      {
        id: 'updated_at',
        header: 'Last Updated',
        accessorKey: 'updated_at',
        size: 120,
        maxSize: 120,
        cell: ({ getValue }) => (
          <span className="text-xs text-text-muted">
            {new Date(getValue() as string).toLocaleDateString()}
          </span>
        ),
      },
    ];
  }, [
    editingCell,
    editValue,
    expandedRows,
    handleCellEdit,
    handleToggleActive,
    handleAddProviderMapping,
    handleToggleExpandRow,
  ]);

  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:4000
        </p>
      </div>
    );
  }

  const renderExpandedRow = (exchange: Exchange) => {
    const mappings = expandedRowData[exchange.id] || [];
    
    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: {new Date(mapping.created_at).toLocaleDateString()}</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 (
    <>
      <div className="space-y-0">
        <DataTable
          data={exchanges || []}
          columns={columns}
          loading={loading}
          className="rounded-lg border border-border"
        />
        
        {/* Expanded rows */}
        {Array.from(expandedRows).map(exchangeId => {
          const exchange = exchanges?.find(e => e.id === exchangeId);
          if (!exchange) return null;
          
          return (
            <div key={`expanded-${exchangeId}`} className="border-l border-r border-b border-border rounded-b-lg -mt-1">
              {renderExpandedRow(exchange)}
            </div>
          );
        })}
      </div>

      {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();
            }
          }}
        />
      )}
    </>
  );
}
