import React, { useState, useEffect } from 'react';
import {
  Modal,
  TextInput,
  Select,
  NumberInput,
  Button,
  Group,
  Stack,
  Text,
  Paper,
  Divider,
  JsonInput,
  Box,
} from '@mantine/core';
import { useForm } from '@mantine/form';
import { notifications } from '@mantine/notifications';
import Editor from '@monaco-editor/react';
import { functionApi, runtimeApi } from '../services/apiService';
import { FunctionDefinition, CreateFunctionRequest, UpdateFunctionRequest, RuntimeType } from '../types';

interface FunctionFormProps {
  opened: boolean;
  onClose: () => void;
  onSuccess: () => void;
  editFunction?: FunctionDefinition;
}

export const FunctionForm: React.FC<FunctionFormProps> = ({
  opened,
  onClose,
  onSuccess,
  editFunction,
}) => {
  const isEditing = !!editFunction;
  const [runtimeOptions, setRuntimeOptions] = useState<Array<{value: string; label: string}>>([]);
  
  // Default images for each runtime
  const DEFAULT_IMAGES: Record<string, string> = {
    'nodejs18': 'node:18-alpine',
    'python3.9': 'python:3.9-alpine',
    'go1.20': 'golang:1.20-alpine',
  };

  // Map runtime to Monaco editor language
  const getEditorLanguage = (runtime: string): string => {
    const languageMap: Record<string, string> = {
      'nodejs18': 'javascript',
      'python3.9': 'python',
      'go1.20': 'go',
    };
    return languageMap[runtime] || 'javascript';
  };

  // Get default code template based on runtime
  const getDefaultCode = (runtime: string): string => {
    const templates: Record<string, string> = {
      'nodejs18': `exports.handler = async (event, context) => {
  console.log('Event:', JSON.stringify(event, null, 2));
  
  return {
    statusCode: 200,
    body: JSON.stringify({
      message: 'Hello from Node.js!',
      timestamp: new Date().toISOString()
    })
  };
};`,
      'python3.9': `import json
from datetime import datetime

def handler(event, context):
    print('Event:', json.dumps(event, indent=2))
    
    return {
        'statusCode': 200,
        'body': json.dumps({
            'message': 'Hello from Python!',
            'timestamp': datetime.now().isoformat()
        })
    }`,
      'go1.20': `package main

import (
    "context"
    "encoding/json"
    "fmt"
    "log"
    "time"
)

type Event map[string]interface{}
type Response struct {
    StatusCode int    \`json:"statusCode"\`
    Body       string \`json:"body"\`
}

func Handler(ctx context.Context, event Event) (Response, error) {
    eventJSON, _ := json.MarshalIndent(event, "", "  ")
    log.Printf("Event: %s", eventJSON)
    
    body := map[string]interface{}{
        "message":   "Hello from Go!",
        "timestamp": time.Now().Format(time.RFC3339),
    }
    
    bodyJSON, _ := json.Marshal(body)
    
    return Response{
        StatusCode: 200,
        Body:       string(bodyJSON),
    }, nil
}`
    };
    return templates[runtime] || templates['nodejs18'];
  };

  useEffect(() => {
    // Fetch available runtimes from backend
    const fetchRuntimes = async () => {
      try {
        const response = await runtimeApi.getRuntimes();
        setRuntimeOptions(response.data.runtimes || []);
      } catch (error) {
        console.error('Failed to fetch runtimes:', error);
        // Fallback to default options
        setRuntimeOptions([
          { value: 'nodejs18', label: 'Node.js 18.x' },
          { value: 'python3.9', label: 'Python 3.9' },
          { value: 'go1.20', label: 'Go 1.20' },
        ]);
      }
    };

    if (opened) {
      fetchRuntimes();
    }
  }, [opened]);

  // Update form values when editFunction changes
  useEffect(() => {
    if (editFunction) {
      form.setValues({
        name: editFunction.name || '',
        app_id: editFunction.app_id || 'default',
        runtime: editFunction.runtime || 'nodejs18' as RuntimeType,
        image: editFunction.image || DEFAULT_IMAGES['nodejs18'] || '',
        handler: editFunction.handler || 'index.handler',
        code: editFunction.code || '',
        environment: editFunction.environment ? JSON.stringify(editFunction.environment, null, 2) : '{}',
        timeout: editFunction.timeout || '30s',
        memory: editFunction.memory || 128,
        owner: {
          type: editFunction.owner?.type || 'team' as const,
          name: editFunction.owner?.name || 'FaaS Team',
          owner: editFunction.owner?.owner || 'admin@example.com',
        },
      });
    } else {
      // Reset to default values when not editing
      form.setValues({
        name: '',
        app_id: 'default',
        runtime: 'nodejs18' as RuntimeType,
        image: DEFAULT_IMAGES['nodejs18'] || '',
        handler: 'index.handler',
        code: getDefaultCode('nodejs18'),
        environment: '{}',
        timeout: '30s',
        memory: 128,
        owner: {
          type: 'team' as const,
          name: 'FaaS Team',
          owner: 'admin@example.com',
        },
      });
    }
  }, [editFunction, opened]);

  const form = useForm({
    initialValues: {
      name: '',
      app_id: 'default',
      runtime: 'nodejs18' as RuntimeType,
      image: DEFAULT_IMAGES['nodejs18'] || '',
      handler: 'index.handler',
      code: getDefaultCode('nodejs18'),
      environment: '{}',
      timeout: '30s',
      memory: 128,
      owner: {
        type: 'team' as const,
        name: 'FaaS Team',
        owner: 'admin@example.com',
      },
    },
    validate: {
      name: (value) => value.length < 1 ? 'Name is required' : null,
      app_id: (value) => value.length < 1 ? 'App ID is required' : null,
      runtime: (value) => !value ? 'Runtime is required' : null,
      image: (value) => value.length < 1 ? 'Image is required' : null,
      handler: (value) => value.length < 1 ? 'Handler is required' : null,
      timeout: (value) => !value.match(/^\d+[smh]$/) ? 'Timeout must be in format like 30s, 5m, 1h' : null,
      memory: (value) => value < 64 || value > 3008 ? 'Memory must be between 64 and 3008 MB' : null,
    },
  });

  const handleRuntimeChange = (runtime: string | null) => {
    if (runtime && DEFAULT_IMAGES[runtime]) {
      form.setFieldValue('image', DEFAULT_IMAGES[runtime]);
    }
    form.setFieldValue('runtime', runtime as RuntimeType);
    
    // If creating a new function and no code is set, provide default template
    if (!isEditing && runtime && (!form.values.code || form.values.code.trim() === '')) {
      form.setFieldValue('code', getDefaultCode(runtime));
    }
  };

  const handleSubmit = async (values: typeof form.values) => {
    console.log('handleSubmit called with values:', values);
    console.log('Form validation errors:', form.errors);
    console.log('Is form valid?', form.isValid());
    
    // Check each field individually
    const fieldNames = ['name', 'app_id', 'runtime', 'image', 'handler', 'timeout', 'memory'];
    fieldNames.forEach(field => {
      const error = form.validateField(field);
      console.log(`Field ${field} error:`, error);
    });
    
    if (!form.isValid()) {
      console.log('Form is not valid, validation errors:', form.errors);
      return;
    }
    try {
      // Parse environment variables JSON
      let parsedEnvironment;
      try {
        parsedEnvironment = values.environment ? JSON.parse(values.environment) : undefined;
      } catch (error) {
        console.error('Error parsing environment variables:', error);
        notifications.show({
          title: 'Error',
          message: 'Invalid JSON in environment variables',
          color: 'red',
        });
        return;
      }
      if (isEditing && editFunction) {
        const updateData: UpdateFunctionRequest = {
          name: values.name,
          runtime: values.runtime,
          image: values.image,
          handler: values.handler,
          code: values.code || undefined,
          environment: parsedEnvironment,
          timeout: values.timeout,
          memory: values.memory,
          owner: values.owner,
        };
        await functionApi.update(editFunction.id, updateData);
        notifications.show({
          title: 'Success',
          message: 'Function updated successfully',
          color: 'green',
        });
      } else {
        const createData: CreateFunctionRequest = {
          name: values.name,
          app_id: values.app_id,
          runtime: values.runtime,
          image: values.image,
          handler: values.handler,
          code: values.code || undefined,
          environment: parsedEnvironment,
          timeout: values.timeout,
          memory: values.memory,
          owner: values.owner,
        };
        await functionApi.create(createData);
        notifications.show({
          title: 'Success',
          message: 'Function created successfully',
          color: 'green',
        });
      }
      onSuccess();
      onClose();
      form.reset();
    } catch (error) {
      console.error('Error saving function:', error);
      notifications.show({
        title: 'Error',
        message: `Failed to ${isEditing ? 'update' : 'create'} function`,
        color: 'red',
      });
    }
  };

  return (
    <Modal
      opened={opened}
      onClose={onClose}
      title={isEditing ? 'Edit Function' : 'Create Function'}
      size="lg"
    >
      <form onSubmit={(e) => {
        console.log('Form submit event triggered');
        console.log('Form values:', form.values);
        console.log('Form errors:', form.errors);
        console.log('Is form valid?', form.isValid());
        const result = form.onSubmit(handleSubmit)(e);
        console.log('Form onSubmit result:', result);
        return result;
      }}>
        <Stack gap="md">
          <Group grow>
            <TextInput
              label="Function Name"
              placeholder="my-function"
              required
              {...form.getInputProps('name')}
            />
            <TextInput
              label="App ID"
              placeholder="my-app"
              required
              disabled={isEditing}
              {...form.getInputProps('app_id')}
            />
          </Group>

          <Group grow>
            <Select
              label="Runtime"
              placeholder="Select runtime"
              required
              data={runtimeOptions}
              {...form.getInputProps('runtime')}
              onChange={handleRuntimeChange}
            />
            <NumberInput
              label="Memory (MB)"
              placeholder="128"
              required
              min={64}
              max={3008}
              {...form.getInputProps('memory')}
            />
          </Group>

          <Group grow>
            <TextInput
              label="Timeout"
              placeholder="30s"
              required
              {...form.getInputProps('timeout')}
            />
          </Group>

          <TextInput
            label="Handler"
            description="The entry point for your function (e.g., 'index.handler' means handler function in index file)"
            placeholder="index.handler"
            required
            {...form.getInputProps('handler')}
          />

          <Box>
            <Text size="sm" fw={500} mb={5}>
              Function Code
            </Text>
            <Box 
              style={{ 
                border: '1px solid #dee2e6',
                borderRadius: '4px',
                overflow: 'hidden'
              }}
            >
              <Editor
                height="400px"
                language={getEditorLanguage(form.values.runtime)}
                value={form.values.code}
                onChange={(value) => form.setFieldValue('code', value || '')}
                options={{
                  minimap: { enabled: false },
                  scrollBeyondLastLine: false,
                  fontSize: 14,
                  lineNumbers: 'on',
                  roundedSelection: false,
                  scrollbar: {
                    vertical: 'visible',
                    horizontal: 'visible'
                  },
                  automaticLayout: true,
                  wordWrap: 'on',
                  tabSize: 2,
                  insertSpaces: true,
                  folding: true,
                  lineDecorationsWidth: 0,
                  lineNumbersMinChars: 3,
                  renderLineHighlight: 'line',
                  selectOnLineNumbers: true,
                  theme: 'vs-light'
                }}
                loading={<Text ta="center" p="xl">Loading editor...</Text>}
              />
            </Box>
            {form.errors.code && (
              <Text size="xs" c="red" mt={5}>
                {form.errors.code}
              </Text>
            )}
          </Box>

          <JsonInput
            label="Environment Variables"
            description="JSON object with key-value pairs that will be available in your function runtime"
            placeholder={`{
  "NODE_ENV": "production",
  "API_URL": "https://api.example.com",
  "DATABASE_HOST": "db.example.com",
  "LOG_LEVEL": "info"
}`}
            validationError="Invalid JSON - please check your syntax"
            formatOnBlur
            autosize
            minRows={4}
            {...form.getInputProps('environment')}
          />

          <Paper withBorder p="md" bg="gray.0">
            <Text size="sm" fw={500} mb="xs">Owner Information</Text>
            <Group grow>
              <Select
                label="Owner Type"
                data={[
                  { value: 'individual', label: 'Individual' },
                  { value: 'team', label: 'Team' },
                ]}
                {...form.getInputProps('owner.type')}
              />
              <TextInput
                label="Owner Name"
                placeholder="Team Name"
                {...form.getInputProps('owner.name')}
              />
            </Group>
            <TextInput
              label="Owner Email"
              placeholder="owner@example.com"
              mt="xs"
              {...form.getInputProps('owner.owner')}
            />
          </Paper>

          <Divider />

          <Group justify="flex-end">
            <Button variant="light" onClick={onClose}>
              Cancel
            </Button>
            <Button type="submit">
              {isEditing ? 'Update' : 'Create'} Function
            </Button>
          </Group>
        </Stack>
      </form>
    </Modal>
  );
};
