import React, { useEffect, useMemo, useState } from 'react';
import { Pressable, Text, View } from 'react-native';
import { Check } from 'lucide-react-native';

import { useAgentBi } from '../analytics/mixpanelContext';
import { themedColor } from '../theme';
import type { SuperagentToolCall, SuperagentToolRendererProps } from '../types';
import {
  buildBatchApprovalDecisions,
  getEntitySummary,
  PREVIOUS_APPROVAL_NOTE,
  type BatchApprovalDecision,
} from './entityWidgetUtils';
import { ApprovalCard } from './primitives/ApprovalCard';
import { ExpandableSection } from './primitives/ExpandableSection';
import { toolWidgetStyles } from './primitives/toolWidgetStyles';
import { isActionableTurn, parseToolArgs } from './toolWidgetUtils';
import { EntityWriteDetails, hasEntityWriteDetails } from './widgets/EntityWriteWidget';

/**
 * Batch approval for 2+ pending update_entities/delete_entities calls —
 * native port of the web ToolCallsContainer batch UI: one checkbox per
 * pending call, "Approve (n)" approves the checked calls AND rejects the
 * unchecked ones, "Reject All" rejects everything. The web submits through a
 * batch endpoint that resumes each call individually; native has no batch
 * route, so the same per-call approved/rejected submissions go out
 * sequentially (approvals first — the turn resumes after the last one).
 */
export function EntityApprovalBatchCard({
  isLastAssistantMessage,
  submitToolCallInput,
  toolCalls,
}: {
  isLastAssistantMessage?: boolean;
  submitToolCallInput?: SuperagentToolRendererProps['submitToolCallInput'];
  toolCalls: SuperagentToolCall[];
}) {
  const bi = useAgentBi();
  const pendingIds = toolCalls.map((toolCall) => toolCall.id).filter((id): id is string => Boolean(id));
  const pendingIdsKey = pendingIds.join(',');
  const [selectedIds, setSelectedIds] = useState<Set<string>>(() => new Set(pendingIds));
  const [isSubmitting, setIsSubmitting] = useState(false);
  const [error, setError] = useState<string | null>(null);

  // Keep only selections that still exist; re-select all once none remain
  // (web useBatchApproval parity).
  useEffect(() => {
    const currentIds = new Set(pendingIdsKey.split(',').filter(Boolean));
    setSelectedIds((previous) => {
      const kept = new Set([...previous].filter((id) => currentIds.has(id)));
      return kept.size > 0 ? kept : currentIds;
    });
  }, [pendingIdsKey]);

  const toggleSelection = (id: string) => {
    setSelectedIds((previous) => {
      const next = new Set(previous);
      if (next.has(id)) next.delete(id);
      else next.add(id);
      return next;
    });
  };

  const submitDecisions = async (decisions: BatchApprovalDecision[]) => {
    if (!submitToolCallInput) return;
    setIsSubmitting(true);
    setError(null);
    let failed = 0;
    for (const decision of decisions) {
      try {
        const result = await submitToolCallInput(decision.toolCallId, decision.approve, {});
        if (result === null) failed += 1;
      } catch {
        failed += 1;
      }
    }
    if (failed > 0) {
      setError(`Failed to process ${failed} of ${decisions.length} changes.`);
    } else {
      const approvedCount = decisions.filter((decision) => decision.approve).length;
      void bi.trackEditor('Entity Write Approval', { batch: true, approved_count: approvedCount, rejected_count: decisions.length - approvedCount });
    }
    setIsSubmitting(false);
  };

  // Stale turn (web useBatchApproval gates batching on isLastAssistantMessage):
  // keep the summary list, drop the buttons.
  const actionableTurn = isActionableTurn(isLastAssistantMessage);
  const canAct = Boolean(submitToolCallInput) && pendingIds.length > 0 && actionableTurn;

  return (
    <ApprovalCard
      approveDisabled={selectedIds.size === 0}
      approveLabel={`Approve (${selectedIds.size})`}
      error={error}
      isSubmitting={isSubmitting}
      onApprove={canAct ? () => submitDecisions(buildBatchApprovalDecisions(pendingIds, selectedIds)) : undefined}
      onReject={canAct ? () => submitDecisions(pendingIds.map((toolCallId) => ({ toolCallId, approve: false }))) : undefined}
      rejectLabel="Reject All"
      title={`${toolCalls.length} changes pending`}
      unavailableNote={actionableTurn ? undefined : PREVIOUS_APPROVAL_NOTE}
    >
      <View>
        {toolCalls.map((toolCall, index) => (
          <BatchApprovalItem
            disabled={isSubmitting || !actionableTurn}
            isSelected={Boolean(toolCall.id && selectedIds.has(toolCall.id))}
            key={toolCall.id ?? index}
            onToggleSelect={toolCall.id ? () => toggleSelection(toolCall.id!) : undefined}
            toolCall={toolCall}
          />
        ))}
      </View>
    </ApprovalCard>
  );
}

function BatchApprovalItem({
  disabled,
  isSelected,
  onToggleSelect,
  toolCall,
}: {
  disabled: boolean;
  isSelected: boolean;
  onToggleSelect?: () => void;
  toolCall: SuperagentToolCall;
}) {
  const args = useMemo(() => parseToolArgs(toolCall), [toolCall]);
  const toolName = toolCall.name || '';
  const summary = getEntitySummary(toolName, args);

  return (
    <View style={toolWidgetStyles.approvalItem}>
      <Pressable
        accessibilityRole="checkbox"
        accessibilityState={{ checked: isSelected, disabled }}
        disabled={disabled || !onToggleSelect}
        onPress={onToggleSelect}
        style={[toolWidgetStyles.approvalCheckbox, isSelected && toolWidgetStyles.approvalCheckboxChecked]}
      >
        {isSelected ? <Check color={themedColor('#111111')} size={13} strokeWidth={3} /> : null}
      </Pressable>
      <View style={toolWidgetStyles.approvalItemBody}>
        {hasEntityWriteDetails(toolName, args) ? (
          <ExpandableSection collapsedTitle={summary} titleStyle={toolWidgetStyles.approvalSummaryText}>
            <EntityWriteDetails args={args} toolName={toolName} />
          </ExpandableSection>
        ) : (
          <Text style={toolWidgetStyles.approvalSummaryText}>{summary}</Text>
        )}
      </View>
    </View>
  );
}
