import React, { useState, useEffect } from 'react';
import {
  Table,
  Button,
  Stack,
  Title,
  Modal,
  Select,
  TextInput,
  Pagination,
  Group,
  ActionIcon,
  Badge,
  Card,
  Text,
  Loader,
  Alert,
  Code,
  ScrollArea,
  Flex,
} from '@mantine/core';
import {
  IconRefresh,
  IconEye,
  IconX,
  IconSearch,
  IconClock,
} from '@tabler/icons-react';
import { executionApi, functionApi } from '../services/apiService';
import { FunctionExecution, FunctionDefinition } from '../types';
import { notifications } from '@mantine/notifications';

const ExecutionList: React.FC = () => {
  const [executions, setExecutions] = useState<FunctionExecution[]>([]);
  const [functions, setFunctions] = useState<FunctionDefinition[]>([]);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState<string | null>(null);
  const [selectedFunction, setSelectedFunction] = useState<string>('');
  const [searchTerm, setSearchTerm] = useState('');
  const [page, setPage] = useState(1);
  const [totalPages, setTotalPages] = useState(1);
  const [selectedExecution, setSelectedExecution] = useState<FunctionExecution | null>(null);
  const [executionLogs, setExecutionLogs] = useState<string[]>([]);
  const [logsModalOpened, setLogsModalOpened] = useState(false);
  const [logsLoading, setLogsLoading] = useState(false);

  const limit = 20;

  const loadExecutions = async () => {
    try {
      setLoading(true);
      setError(null);
      
      const offset = (page - 1) * limit;
      const functionId = selectedFunction || undefined;
      
      const response = await executionApi.list(functionId, limit, offset);
      setExecutions(response.data.executions || []);
      
      // Calculate total pages (rough estimate)
      const hasMore = response.data.executions?.length === limit;
      setTotalPages(hasMore ? page + 1 : page);
      
    } catch (err: any) {
      setError(err.response?.data?.error || 'Failed to load executions');
      console.error('Error loading executions:', err);
    } finally {
      setLoading(false);
    }
  };

  const loadFunctions = async () => {
    try {
      const response = await functionApi.list();
      setFunctions(response.data.functions || []);
    } catch (err) {
      console.error('Error loading functions:', err);
    }
  };

  useEffect(() => {
    loadFunctions();
  }, []);

  useEffect(() => {
    loadExecutions();
  }, [page, selectedFunction]);

  const handleRefresh = () => {
    loadExecutions();
  };

  const handleViewLogs = async (execution: FunctionExecution) => {
    setSelectedExecution(execution);
    setLogsModalOpened(true);
    setLogsLoading(true);
    
    try {
      const response = await executionApi.getLogs(execution.id);
      setExecutionLogs(response.data.logs || []);
    } catch (err: any) {
      notifications.show({
        title: 'Error',
        message: err.response?.data?.error || 'Failed to load logs',
        color: 'red',
      });
      setExecutionLogs([]);
    } finally {
      setLogsLoading(false);
    }
  };

  const handleCancelExecution = async (executionId: string) => {
    try {
      await executionApi.cancel(executionId);
      notifications.show({
        title: 'Success',
        message: 'Execution cancelled successfully',
        color: 'green',
      });
      loadExecutions();
    } catch (err: any) {
      notifications.show({
        title: 'Error',
        message: err.response?.data?.error || 'Failed to cancel execution',
        color: 'red',
      });
    }
  };

  const getStatusColor = (status: FunctionExecution['status']) => {
    switch (status) {
      case 'completed':
        return 'green';
      case 'failed':
        return 'red';
      case 'running':
        return 'blue';
      case 'pending':
        return 'yellow';
      case 'timeout':
        return 'orange';
      case 'canceled':
        return 'gray';
      default:
        return 'gray';
    }
  };

  const formatDuration = (nanoseconds: number) => {
    if (!nanoseconds) return 'N/A';
    const milliseconds = nanoseconds / 1000000;
    if (milliseconds < 1000) {
      return `${milliseconds.toFixed(0)}ms`;
    }
    return `${(milliseconds / 1000).toFixed(2)}s`;
  };

  const formatMemory = (bytes: number) => {
    if (!bytes) return 'N/A';
    if (bytes < 1024 * 1024) {
      return `${(bytes / 1024).toFixed(0)}KB`;
    }
    return `${(bytes / (1024 * 1024)).toFixed(1)}MB`;
  };

  const formatDate = (dateString: string) => {
    return new Date(dateString).toLocaleString();
  };

  const getFunctionName = (functionId: string) => {
    const func = functions.find(f => f.id === functionId);
    return func?.name || 'Unknown Function';
  };

  const filteredExecutions = executions.filter(execution => {
    if (!searchTerm) return true;
    const functionName = getFunctionName(execution.function_id);
    return functionName.toLowerCase().includes(searchTerm.toLowerCase()) ||
           execution.id.toLowerCase().includes(searchTerm.toLowerCase()) ||
           execution.status.toLowerCase().includes(searchTerm.toLowerCase());
  });

  if (loading && executions.length === 0) {
    return (
      <Stack gap="lg">
        <Group justify="space-between">
          <Title order={2}>Function Executions</Title>
          <Button
            leftSection={<IconRefresh size={16} />}
            onClick={handleRefresh}
            loading={loading}
          >
            Refresh
          </Button>
        </Group>

        <Stack align="center" justify="center" h={200}>
          <Loader size="lg" />
          <Text>Loading executions...</Text>
        </Stack>
      </Stack>
    );
  }

  return (
    <Stack gap="lg">
      <Group justify="space-between">
        <Title order={2}>Function Executions</Title>
        <Button
          leftSection={<IconRefresh size={16} />}
          onClick={handleRefresh}
          loading={loading}
        >
          Refresh
        </Button>
      </Group>

      <Group>
        <TextInput
          placeholder="Search executions..."
          value={searchTerm}
          onChange={(event) => setSearchTerm(event.currentTarget.value)}
          leftSection={<IconSearch size={16} />}
          style={{ width: 300 }}
        />
        <Select
          placeholder="All Functions"
          data={functions.map(f => ({ value: f.id, label: f.name }))}
          value={selectedFunction}
          onChange={(value) => {
            setSelectedFunction(value || '');
            setPage(1);
          }}
          clearable
          style={{ width: 200 }}
        />
      </Group>

      {error && (
        <Alert color="red" title="Error">
          {error}
        </Alert>
      )}

      {filteredExecutions.length === 0 ? (
        <Card shadow="sm" radius="md" withBorder p="xl">
          <Stack align="center" gap="md">
            <IconClock size={48} color="gray" />
            <div style={{ textAlign: 'center' }}>
              <Text fw={500} mb="xs">
                No executions found
              </Text>
              <Text size="sm" c="dimmed">
                There are no function executions matching your current filters
              </Text>
            </div>
          </Stack>
        </Card>
      ) : (
        <Card shadow="sm" radius="md" withBorder>
          <Table>
            <Table.Thead>
              <Table.Tr>
                <Table.Th>Function</Table.Th>
                <Table.Th>Status</Table.Th>
                <Table.Th>Duration</Table.Th>
                <Table.Th>Memory</Table.Th>
                <Table.Th>Started</Table.Th>
                <Table.Th>Actions</Table.Th>
              </Table.Tr>
            </Table.Thead>
            <Table.Tbody>
              {filteredExecutions.map((execution) => (
                <Table.Tr key={execution.id}>
                  <Table.Td>
                    <Stack gap={2}>
                      <Text fw={500}>{getFunctionName(execution.function_id)}</Text>
                      <Code style={{ fontSize: '12px' }}>{execution.id.slice(0, 8)}...</Code>
                    </Stack>
                  </Table.Td>
                  <Table.Td>
                    <Badge color={getStatusColor(execution.status)} variant="light">
                      {execution.status}
                    </Badge>
                  </Table.Td>
                  <Table.Td>
                    <Group gap="xs">
                      <IconClock size={14} />
                      <Text size="sm">{formatDuration(execution.duration)}</Text>
                    </Group>
                  </Table.Td>
                  <Table.Td>
                    <Group gap="xs">
                      {/* <IconMemory size={14} /> */}
                      <Text size="sm">{formatMemory(execution.memory_used)}</Text>
                    </Group>
                  </Table.Td>
                  <Table.Td>
                    <Text size="sm">{formatDate(execution.created_at)}</Text>
                  </Table.Td>
                  <Table.Td>
                    <Group gap="xs">
                      <ActionIcon
                        size="sm"
                        variant="subtle"
                        onClick={() => handleViewLogs(execution)}
                        title="View Logs"
                      >
                        <IconEye size={16} />
                      </ActionIcon>
                      {(execution.status === 'running' || execution.status === 'pending') && (
                        <ActionIcon
                          size="sm"
                          variant="subtle"
                          color="red"
                          onClick={() => handleCancelExecution(execution.id)}
                          title="Cancel Execution"
                        >
                          <IconX size={16} />
                        </ActionIcon>
                      )}
                    </Group>
                  </Table.Td>
                </Table.Tr>
              ))}
            </Table.Tbody>
          </Table>
        </Card>
      )}

      {totalPages > 1 && (
        <Group justify="center">
          <Pagination
            value={page}
            onChange={setPage}
            total={totalPages}
            size="sm"
          />
        </Group>
      )}

      {/* Logs Modal */}
      <Modal
        opened={logsModalOpened}
        onClose={() => setLogsModalOpened(false)}
        title={`Execution Logs - ${selectedExecution?.id.slice(0, 8)}...`}
        size="xl"
      >
        <Stack gap="md">
          {selectedExecution && (
            <Card>
              <Group justify="space-between">
                <Stack gap="xs">
                  <Text size="sm"><strong>Function:</strong> {getFunctionName(selectedExecution.function_id)}</Text>
                  <Text size="sm"><strong>Status:</strong> <Badge color={getStatusColor(selectedExecution.status)}>{selectedExecution.status}</Badge></Text>
                </Stack>
                <Stack gap="xs" align="flex-end">
                  <Text size="sm"><strong>Duration:</strong> {formatDuration(selectedExecution.duration)}</Text>
                  <Text size="sm"><strong>Memory:</strong> {formatMemory(selectedExecution.memory_used)}</Text>
                </Stack>
              </Group>
              
              {selectedExecution.input && (
                <div>
                  <Text size="sm" fw={500} mt="md" mb="xs">Input:</Text>
                  <Code block>{JSON.stringify(selectedExecution.input, null, 2)}</Code>
                </div>
              )}
              
              {selectedExecution.output && (
                <div>
                  <Text size="sm" fw={500} mt="md" mb="xs">Output:</Text>
                  <Code block>{JSON.stringify(selectedExecution.output, null, 2)}</Code>
                </div>
              )}
              
              {selectedExecution.error && (
                <div>
                  <Text size="sm" fw={500} mt="md" mb="xs">Error:</Text>
                  <Code block c="red">{selectedExecution.error}</Code>
                </div>
              )}
            </Card>
          )}

          <div>
            <Text size="sm" fw={500} mb="xs">Container Logs:</Text>
            {logsLoading ? (
              <Flex justify="center" p="md">
                <Loader size="sm" />
              </Flex>
            ) : executionLogs.length === 0 ? (
              <Text c="dimmed" ta="center" p="md">No logs available</Text>
            ) : (
              <ScrollArea h={300}>
                <Code block>
                  {executionLogs.join('\n')}
                </Code>
              </ScrollArea>
            )}
          </div>
        </Stack>
      </Modal>
    </Stack>
  );
};

export default ExecutionList;
