import React, { useState, useEffect } from 'react';
import {
  Stack,
  Title,
  Card,
  TextInput,
  Textarea,
  Button,
  Group,
  Text,
  Alert,
  Badge,
  Divider,
  Select,
  MultiSelect,
  Code,
  Grid,
  Loader,
  JsonInput,
} from '@mantine/core';
import {
  IconTestPipe,
  IconCheck,
  IconX,
  IconAlertCircle,
  IconClock,
  IconUser,
  IconKey,
} from '@tabler/icons-react';
import { useForm } from '@mantine/form';
import { notifications } from '@mantine/notifications';
import {
  apiService,
  Application,
  VerifyRequest,
  VerifyResponse,
} from '../services/apiService';
import dayjs from 'dayjs';

const TokenTester: React.FC = () => {
  const [applications, setApplications] = useState<Application[]>([]);
  const [testing, setTesting] = useState(false);
  const [result, setResult] = useState<VerifyResponse | null>(null);

  const form = useForm<VerifyRequest>({
    initialValues: {
      app_id: '',
      user_id: '',
      token: '',
      permissions: [],
    },
    validate: {
      app_id: (value) => value.length < 1 ? 'Application is required' : null,
      token: (value) => value.length < 1 ? 'Token is required' : null,
    },
  });

  const availablePermissions = [
    'app.read',
    'app.write',
    'app.delete',
    'token.read',
    'token.create',
    'token.revoke',
    'repo.read',
    'repo.write',
    'repo.admin',
    'permission.read',
    'permission.write',
  ];

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

  const loadApplications = async () => {
    try {
      const response = await apiService.getApplications(100, 0);
      setApplications(response.data);
    } catch (error) {
      console.error('Failed to load applications:', error);
    }
  };

  const handleSubmit = async (values: VerifyRequest) => {
    try {
      setTesting(true);
      setResult(null);
      
      // Clean up the request - remove empty fields
      const cleanedValues = {
        ...values,
        user_id: values.user_id || undefined,
        permissions: values.permissions && values.permissions.length > 0 ? values.permissions : undefined,
      };

      const response = await apiService.verifyToken(cleanedValues);
      setResult(response);
      
      if (response.valid) {
        notifications.show({
          title: 'Token Verified',
          message: `Token is ${response.permitted ? 'valid and permitted' : 'valid but not permitted'}`,
          color: response.permitted ? 'green' : 'orange',
        });
      } else {
        notifications.show({
          title: 'Token Invalid',
          message: response.error || 'Token verification failed',
          color: 'red',
        });
      }
    } catch (error) {
      console.error('Failed to verify token:', error);
      notifications.show({
        title: 'Error',
        message: 'Failed to verify token',
        color: 'red',
      });
    } finally {
      setTesting(false);
    }
  };

  const getStatusColor = (result: VerifyResponse) => {
    if (!result.valid) return 'red';
    if (result.valid && result.permitted) return 'green';
    return 'orange';
  };

  const getStatusIcon = (result: VerifyResponse) => {
    if (!result.valid) return IconX;
    if (result.valid && result.permitted) return IconCheck;
    return IconAlertCircle;
  };

  return (
    <Stack gap="lg">
      <div>
        <Title order={2} mb="xs">
          Token Tester
        </Title>
        <Text c="dimmed">
          Test and verify API tokens against your applications
        </Text>
      </div>

      <Grid>
        <Grid.Col span={{ base: 12, md: 6 }}>
          <Card shadow="sm" radius="md" withBorder p="lg">
            <Title order={3} mb="md">
              Test Configuration
            </Title>
            
            <form onSubmit={form.onSubmit(handleSubmit)}>
              <Stack gap="md">
                <Select
                  label="Application"
                  placeholder="Select an application to test against"
                  required
                  data={applications.map(app => ({
                    value: app.app_id,
                    label: `${app.app_id} (${app.type.join(', ')})`,
                  }))}
                  {...form.getInputProps('app_id')}
                />

                <TextInput
                  label="User ID (Optional)"
                  placeholder="user@example.com"
                  description="Leave empty for token-only verification"
                  {...form.getInputProps('user_id')}
                />

                <Textarea
                  label="Token"
                  placeholder="Paste your token here..."
                  required
                  minRows={3}
                  {...form.getInputProps('token')}
                />

                <MultiSelect
                  label="Required Permissions (Optional)"
                  placeholder="Select permissions to test"
                  description="Leave empty to skip permission checks"
                  data={availablePermissions.map(perm => ({
                    value: perm,
                    label: perm,
                  }))}
                  {...form.getInputProps('permissions')}
                  searchable
                />

                <Group justify="flex-end">
                  <Button
                    type="submit"
                    loading={testing}
                    leftSection={!testing ? <IconTestPipe size={16} /> : <Loader size={16} />}
                    disabled={applications.length === 0}
                  >
                    {testing ? 'Testing...' : 'Test Token'}
                  </Button>
                </Group>
              </Stack>
            </form>
          </Card>
        </Grid.Col>

        <Grid.Col span={{ base: 12, md: 6 }}>
          <Card shadow="sm" radius="md" withBorder p="lg" h="100%">
            <Title order={3} mb="md">
              Test Results
            </Title>

            {!result && !testing && (
              <Stack align="center" justify="center" h={300}>
                <IconTestPipe size={48} color="gray" />
                <Text c="dimmed" ta="center">
                  Configure your test parameters and click "Test Token" to see results
                </Text>
              </Stack>
            )}

            {testing && (
              <Stack align="center" justify="center" h={300}>
                <Loader size="lg" />
                <Text>Verifying token...</Text>
              </Stack>
            )}

            {result && (
              <Stack gap="md">
                <Alert
                  icon={React.createElement(getStatusIcon(result), { size: 16 })}
                  title={
                    !result.valid
                      ? 'Token Invalid'
                      : result.permitted
                      ? 'Token Valid & Permitted'
                      : 'Token Valid but Not Permitted'
                  }
                  color={getStatusColor(result)}
                >
                  {result.error || (
                    result.valid && result.permitted
                      ? 'Token is valid and has the required permissions'
                      : result.valid
                      ? 'Token is valid but lacks some required permissions'
                      : 'Token verification failed'
                  )}
                </Alert>

                <Divider />

                <Stack gap="xs">
                  <Group justify="space-between">
                    <Text fw={500}>Valid:</Text>
                    <Badge color={result.valid ? 'green' : 'red'} variant="light">
                      {result.valid ? 'Yes' : 'No'}
                    </Badge>
                  </Group>

                  <Group justify="space-between">
                    <Text fw={500}>Permitted:</Text>
                    <Badge color={result.permitted ? 'green' : 'red'} variant="light">
                      {result.permitted ? 'Yes' : 'No'}
                    </Badge>
                  </Group>

                  <Group justify="space-between">
                    <Text fw={500}>Token Type:</Text>
                    <Badge variant="light">
                      {result.token_type}
                    </Badge>
                  </Group>

                  {result.user_id && (
                    <Group justify="space-between">
                      <Text fw={500}>User ID:</Text>
                      <Text size="sm" style={{ fontFamily: 'monospace' }}>
                        {result.user_id}
                      </Text>
                    </Group>
                  )}

                  {result.expires_at && (
                    <Group justify="space-between">
                      <Text fw={500}>Expires At:</Text>
                      <Text size="sm">
                        {dayjs(result.expires_at).format('MMM DD, YYYY HH:mm')}
                      </Text>
                    </Group>
                  )}

                  {result.max_valid_at && (
                    <Group justify="space-between">
                      <Text fw={500}>Max Valid Until:</Text>
                      <Text size="sm">
                        {dayjs(result.max_valid_at).format('MMM DD, YYYY HH:mm')}
                      </Text>
                    </Group>
                  )}
                </Stack>

                {result.permissions && result.permissions.length > 0 && (
                  <>
                    <Divider />
                    <div>
                      <Text fw={500} mb="xs">Token Permissions:</Text>
                      <Group gap="xs">
                        {result.permissions.map((perm) => (
                          <Badge key={perm} variant="light" size="sm" color="blue">
                            {perm}
                          </Badge>
                        ))}
                      </Group>
                    </div>
                  </>
                )}

                {result.permission_results && Object.keys(result.permission_results).length > 0 && (
                  <>
                    <Divider />
                    <div>
                      <Text fw={500} mb="xs">Permission Check Results:</Text>
                      <Stack gap="xs">
                        {Object.entries(result.permission_results).map(([permission, granted]) => (
                          <Group key={permission} justify="space-between">
                            <Text size="sm" style={{ fontFamily: 'monospace' }}>
                              {permission}
                            </Text>
                            <Badge color={granted ? 'green' : 'red'} variant="light" size="sm">
                              {granted ? 'Granted' : 'Denied'}
                            </Badge>
                          </Group>
                        ))}
                      </Stack>
                    </div>
                  </>
                )}

                {result.claims && Object.keys(result.claims).length > 0 && (
                  <>
                    <Divider />
                    <div>
                      <Text fw={500} mb="xs">Token Claims:</Text>
                      <Code block>
                        {JSON.stringify(result.claims, null, 2)}
                      </Code>
                    </div>
                  </>
                )}
              </Stack>
            )}
          </Card>
        </Grid.Col>
      </Grid>

      {applications.length === 0 && (
        <Alert
          icon={<IconAlertCircle size={16} />}
          title="No Applications Found"
          color="yellow"
        >
          You need to create at least one application before you can test tokens.
        </Alert>
      )}
    </Stack>
  );
};

export default TokenTester;