import { useState } from 'react';
import { Box, Text } from 'ink';
import { TextInput, Spinner } from '@inkjs/ui';
import type { McpTool, McpSession } from '../mcp-session.js';

interface BeginSessionViewProps {
  tool: McpTool;
  session: McpSession;
  onDone: (result: unknown) => void;
  onError: (msg: string) => void;
  onBack: () => void;
  onLoadingChange?: (loading: boolean) => void;
}

interface SchemaProperty {
  type?: string;
  description?: string;
  items?: { type?: string };
  maxItems?: number;
}

/**
 * Dynamically renders a form for the begin_session tool based on its
 * inputSchema from the MCP protocol. Adapts to whatever the server sends:
 * - string properties → text input
 * - array of strings → comma-separated text input
 * - multiple/unknown properties → raw JSON input
 */
export function BeginSessionView({ tool, session, onDone, onError, onLoadingChange }: BeginSessionViewProps) {
  const [loading, _setLoading] = useState(false);
  const setLoading = (v: boolean) => { _setLoading(v); onLoadingChange?.(v); };
  const [input, setInput] = useState('');

  const schema = tool.inputSchema as {
    properties?: Record<string, SchemaProperty>;
    required?: string[];
  } | undefined;

  const properties = schema?.properties ?? {};
  const propEntries = Object.entries(properties);

  // Determine mode: focused single-property or generic JSON
  const singleProp = propEntries.length === 1 ? propEntries[0]! : null;
  const propName = singleProp?.[0];
  const propDef = singleProp?.[1];
  const isArray = propDef?.type === 'array';

  const buildArgs = (): Record<string, unknown> | null => {
    if (!singleProp) {
      // JSON mode
      try {
        return JSON.parse(input) as Record<string, unknown>;
      } catch {
        onError('Invalid JSON');
        return null;
      }
    }

    const trimmed = input.trim();
    if (trimmed.length === 0) {
      onError(`${propName} is required`);
      return null;
    }

    if (isArray) {
      const items = trimmed
        .split(',')
        .map((t) => t.trim())
        .filter((t) => t.length > 0);
      if (items.length === 0) {
        onError(`Enter at least one value for ${propName}`);
        return null;
      }
      return { [propName!]: items };
    }

    return { [propName!]: trimmed };
  };

  const handleSubmit = async () => {
    const args = buildArgs();
    if (!args) return;

    setLoading(true);
    try {
      const result = await session.callTool(tool.name, args);
      onDone(result);
    } catch (err) {
      onError(`${tool.name} failed: ${err instanceof Error ? err.message : String(err)}`);
      setLoading(false);
    }
  };

  if (loading) {
    return (
      <Box gap={1}>
        <Spinner label={`Calling ${tool.name}...`} />
      </Box>
    );
  }

  // Focused single-property mode
  if (singleProp) {
    const label = propDef?.description ?? propName!;
    const hint = isArray ? 'comma-separated values' : 'text';

    return (
      <Box flexDirection="column">
        <Text bold>{tool.description ?? tool.name}</Text>
        <Text dimColor>{label}</Text>
        <Box marginTop={1}>
          <Text color="cyan">{propName}: </Text>
          <TextInput
            placeholder={hint}
            onChange={setInput}
            onSubmit={handleSubmit}
          />
        </Box>
      </Box>
    );
  }

  // Multi-property / unknown schema → JSON input
  return (
    <Box flexDirection="column">
      <Text bold>{tool.description ?? tool.name}</Text>
      {propEntries.length > 0 && (
        <Box flexDirection="column" marginTop={1}>
          <Text bold>Schema:</Text>
          {propEntries.map(([name, def]) => (
            <Text key={name} dimColor>
              {name}: {def.type ?? 'any'}{def.description ? ` — ${def.description}` : ''}
            </Text>
          ))}
        </Box>
      )}
      <Box flexDirection="column" marginTop={1}>
        <Text bold>Arguments (JSON):</Text>
        <Box>
          <Text color="cyan">&gt; </Text>
          <TextInput
            placeholder="{}"
            defaultValue="{}"
            onChange={setInput}
            onSubmit={handleSubmit}
          />
        </Box>
      </Box>
    </Box>
  );
}
