import React, { useEffect, useRef, useState } from 'react';
import { XCard, registerCatalog } from '@ant-design/x-card';
import type { ActionPayload, XAgentCommand_v0_9 } from '@ant-design/x-card';
import { Alert, Button, Flex, Popconfirm, Steps, Table, Tag, Typography } from 'antd';
import type { TableProps } from 'antd';
import type {
  AiReviewRow,
  AiReviewSchema,
  AiReviewSection,
  AiReviewSectionStatus,
  AiReviewSectionType,
} from './types';

const REVIEW_CATALOG_ID = 'gongxue-review-catalog';

registerCatalog({
  catalogId: REVIEW_CATALOG_ID,
  components: {
    ReviewPreview: {
      type: 'object',
      properties: {
        review: { type: 'object' },
        disabled: { type: 'boolean' },
        activeKey: { type: 'string' },
        activeType: { type: 'string' },
        submittingKey: { type: ['string', 'null'] },
        submittingGroup: { type: 'boolean' },
        error: { type: ['string', 'null'] },
      },
    },
  },
});

function surfaceId(reviewId: string): string {
  return `review-${reviewId}`;
}

const SECTION_TYPE_LABELS: Record<AiReviewSectionType, string> = {
  students: '学生',
  rooms: '宿舍',
  transfers: '换宿',
  checkins: '入住记录',
};

const SECTION_ORDER: AiReviewSectionType[] = [
  'students',
  'rooms',
  'transfers',
  'checkins',
];

const SECTION_DEPENDENCIES: Record<AiReviewSectionType, AiReviewSectionType[]> = {
  students: [],
  rooms: [],
  transfers: ['students', 'rooms'],
  checkins: [],
};

function sectionType(section: Pick<AiReviewSection, 'key' | 'type'>): AiReviewSectionType {
  if (
    section.type === 'students' ||
    section.type === 'rooms' ||
    section.type === 'transfers' ||
    section.type === 'checkins'
  ) {
    return section.type;
  }
  const key = section.key as AiReviewSectionType;
  if (key === 'students' || key === 'rooms' || key === 'transfers' || key === 'checkins') {
    return key;
  }
  const prefix = SECTION_ORDER.find((type) => section.key.startsWith(`${type}_`));
  return prefix ?? 'students';
}

function sectionCount(section: AiReviewSection): number {
  return section.rows.length;
}

function sectionStatus(section: AiReviewSection): AiReviewSectionStatus {
  return section.status ?? 'pending';
}

function sectionResultText(section: AiReviewSection): string {
  if (!section.resultSummary) return '';
  try {
    const parsed = JSON.parse(section.resultSummary) as { message?: unknown };
    if (typeof parsed.message === 'string') return parsed.message;
  } catch {
    // Older data may store a plain text summary.
  }
  return section.resultSummary;
}

const SECTION_STATUS_LABELS: Record<AiReviewSectionStatus, string> = {
  pending: '待确认',
  submitted: '已导入',
  failed: '失败',
  skipped: '已跳过',
};

type GroupStatus = 'pending' | 'partial' | 'submitted' | 'failed' | 'importing';

const GROUP_STATUS_LABELS: Record<GroupStatus, string> = {
  pending: '待确认',
  partial: '部分完成',
  submitted: '已导入',
  failed: '失败',
  importing: '导入中',
};

function groupSections(
  sections: AiReviewSection[],
  type: AiReviewSectionType,
): AiReviewSection[] {
  return sections.filter((section) => sectionType(section) === type);
}

function groupStatus(
  sections: AiReviewSection[],
  type: AiReviewSectionType,
  submittingKey: string | null,
  submittingGroup: boolean,
  activeType?: AiReviewSectionType,
): GroupStatus {
  const items = groupSections(sections, type);
  if (items.length === 0) return 'pending';
  if (
    (submittingGroup && type === activeType) ||
    items.some((item) => submittingKey === item.key)
  ) {
    return 'importing';
  }
  if (items.some((item) => sectionStatus(item) === 'failed')) return 'failed';
  if (items.every((item) => sectionStatus(item) === 'submitted')) return 'submitted';
  return 'partial';
}

function dependencyHint(
  sections: AiReviewSection[],
  type: AiReviewSectionType,
): { step: number; title: string } | null {
  for (const dependencyType of SECTION_DEPENDENCIES[type] ?? []) {
    const matches = groupSections(sections, dependencyType);
    if (matches.length === 0) {
      return { step: -1, title: SECTION_TYPE_LABELS[dependencyType] };
    }
    for (const section of matches) {
      if (sectionStatus(section) !== 'submitted') {
        return { step: sections.indexOf(section), title: section.title };
      }
    }
  }
  return null;
}

function errorMessage(reason: unknown): string {
  if (reason instanceof Error) return reason.message;
  if (reason && typeof reason === 'object' && 'message' in reason) {
    return String((reason as { message?: unknown }).message ?? '确认失败，请稍后重试');
  }
  return '确认失败，请稍后重试';
}

function SectionTable({ section }: { section: AiReviewSection }) {
  const columns: TableProps<AiReviewRow>['columns'] = section.columns.map((column) => ({
    title: column.title,
    dataIndex: column.key,
    key: column.key,
    ellipsis: true,
    render: (value: unknown) =>
      value === null || value === undefined || value === '' ? (
        <Typography.Text type="secondary">-</Typography.Text>
      ) : (
        String(value)
      ),
  }));
  return (
    <Table<AiReviewRow>
      size="small"
      rowKey="__rowKey"
      columns={columns}
      dataSource={section.rows.map((row, index) => ({ ...row, __rowKey: `row-${index}` }))}
      pagination={{ pageSize: 10, size: 'small', hideOnSinglePage: true }}
      scroll={{ x: 'max-content' }}
    />
  );
}

interface ReviewPreviewProps {
  review?: AiReviewSchema;
  disabled?: boolean;
  onAction?: (name: string, context: Record<string, unknown>) => void;
}

const ReviewPreview: React.FC<ReviewPreviewProps> = ({ review, disabled, onAction }) => {
  if (!review) return null;
  const submitted = review.status === 'submitted';
  const expired = review.status === 'expired';
  const runtime = review as unknown as {
    submitting?: boolean;
    activeKey?: string;
    activeType?: string;
    submittingKey?: string | null;
    submittingGroup?: boolean;
    error?: string | null;
  };
  const submitting = Boolean(runtime.submitting);
  const submittingKey = runtime.submittingKey ?? null;
  const submittingGroup = Boolean(runtime.submittingGroup);
  const sections = review.sections;
  const presentTypes = SECTION_ORDER.filter((type) =>
    sections.some((section) => sectionType(section) === type),
  );
  const activeType = presentTypes.includes(runtime.activeType as AiReviewSectionType)
    ? (runtime.activeType as AiReviewSectionType)
    : presentTypes[0];
  if (!activeType) return null;
  const activeSection =
    sections.find((section) => section.key === runtime.activeKey) ??
    groupSections(sections, activeType)[0];
  const activeStatus = activeSection ? sectionStatus(activeSection) : 'pending';
  const dependency =
    activeSection === undefined ? null : dependencyHint(sections, sectionType(activeSection));
  const typeItems = presentTypes.map((type, index) => {
    const items = groupSections(sections, type);
    const status = groupStatus(sections, type, submittingKey, submittingGroup, activeType);
    const stepStatus: 'finish' | 'error' | 'process' | 'wait' =
      status === 'submitted'
        ? 'finish'
        : status === 'failed'
          ? 'error'
          : status === 'importing' || type === activeType
            ? 'process'
            : 'wait';
    return {
      key: type,
      title: `${SECTION_TYPE_LABELS[type]}（${items.reduce((sum, item) => sum + sectionCount(item), 0)}）`,
      content: GROUP_STATUS_LABELS[status],
      status: stepStatus,
      index,
    };
  });
  const group = groupSections(sections, activeType);
  const typeTotal = group.reduce((sum, section) => sum + sectionCount(section), 0);
  const groupDep = dependencyHint(sections, activeType);
  const groupReady =
    !submitted &&
    !expired &&
    !disabled &&
    !submitting &&
    !submittingKey &&
    !submittingGroup &&
    group.length > 0 &&
    !group.every((section) => sectionStatus(section) === 'submitted') &&
    !groupDep;
  const anyRunning = submitting || Boolean(submittingKey) || submittingGroup;
  const allIssues = sections.flatMap((section) => section.issues);
  const allRows = sections.reduce((sum, section) => sum + sectionCount(section), 0);

  return (
    <div className="ai-chat-review-card">
      <Flex justify="space-between" align="center" wrap gap={8}>
        <Typography.Text strong className="ai-chat-review-card__title">
          {review.title}
        </Typography.Text>
        {submitted ? (
          <Tag color="success">已导入</Tag>
        ) : expired ? (
          <Tag>已失效</Tag>
        ) : anyRunning ? (
          <Tag color="processing">导入中</Tag>
        ) : (
          <Tag color="gold">待确认</Tag>
        )}
      </Flex>
      {review.summary && (
        <Typography.Paragraph type="secondary" className="ai-chat-review-card__summary">
          {review.summary}
        </Typography.Paragraph>
      )}
      {expired && (
        <Alert
          type="warning"
          showIcon
          message="此导入预览已被新的预览替代，已失效"
          description="如需导入，请使用最新的预览卡。"
        />
      )}
      <Steps
        size="small"
        current={Math.max(0, typeItems.findIndex((item) => item.key === activeType))}
        items={typeItems.map((item) => ({
          key: item.key,
          title: item.title,
          content: item.content,
          status: item.status,
        }))}
        onChange={(index) => {
          const type = typeItems[index]?.key;
          if (type) onAction?.('review:selectType', { type });
        }}
      />
      {activeType && (
        <Flex vertical gap={8} className="ai-chat-review-card__group">
          <Flex justify="space-between" align="center" wrap gap={8}>
            <Flex vertical gap={2}>
              <Typography.Text strong>
                {SECTION_TYPE_LABELS[activeType]} · 共 {group.length} 张表 / {typeTotal} 行
              </Typography.Text>
              <Typography.Text type="secondary">
                {GROUP_STATUS_LABELS[
                  groupStatus(sections, activeType, submittingKey, submittingGroup, activeType)
                ]}
              </Typography.Text>
            </Flex>
            {groupDep && (
              <Alert
                type="warning"
                showIcon
                message={
                  groupDep.step === -1
                    ? `「${groupDep.title}」分表尚未生成或导入，请先确认前置步骤`
                    : `请先确认第 ${groupDep.step + 1} 步「${groupDep.title}」`
                }
              />
            )}
            {!submitted && !expired && group.length > 0 && (
              <Popconfirm
                title={`确认导入本组 ${group.length} 张表？`}
                description={`本组共 ${typeTotal} 行，确认后将按顺序逐表导入。`}
                okText="确认导入"
                cancelText="取消"
                disabled={!groupReady}
                onConfirm={() =>
                  onAction?.('review:confirmGroup', {
                    reviewId: review.id,
                    type: activeType,
                  })
                }
              >
                <Button
                  type="primary"
                  loading={submittingGroup}
                  disabled={!groupReady}
                >
                  {groupStatus(sections, activeType, submittingKey, submittingGroup, activeType) ===
                  'submitted'
                    ? '已导入'
                    : `确认本组 ${group.length} 张表`}
                </Button>
              </Popconfirm>
            )}
          </Flex>
          <Flex vertical gap={8} className="ai-chat-review-card__sheets">
            {group.map((section, index) => {
              const status = sectionStatus(section);
              const dep = dependencyHint(sections, sectionType(section));
              const canConfirm =
                !submitted &&
                !expired &&
                !disabled &&
                !anyRunning &&
                status !== 'submitted' &&
                status !== 'skipped' &&
                !dep;
              return (
                <Flex
                  key={section.key}
                  justify="space-between"
                  align="center"
                  wrap
                  gap={8}
                  className="ai-chat-review-card__sheet"
                  onClick={() =>
                    onAction?.('review:selectStep', { sectionKey: section.key })
                  }
                >
                  <Flex vertical gap={2} style={{ minWidth: 160 }}>
                    <Typography.Text>
                      {index + 1}. {section.title}
                      {section.sheet ? (
                        <Typography.Text type="secondary">（{section.sheet}）</Typography.Text>
                      ) : null}
                    </Typography.Text>
                    <Typography.Text type="secondary">
                      {sectionCount(section)} 行 · {SECTION_STATUS_LABELS[status]}
                    </Typography.Text>
                  </Flex>
                  <Button
                    size="small"
                    loading={submittingKey === section.key}
                    disabled={!canConfirm}
                    onClick={(event) => {
                      event.stopPropagation();
                      onAction?.('review:confirmStep', {
                        reviewId: review.id,
                        sectionKey: section.key,
                      });
                    }}
                  >
                    {status === 'failed'
                      ? '重试导入本步'
                      : status === 'submitted'
                        ? '已导入'
                        : status === 'skipped'
                          ? '已跳过'
                          : expired
                            ? '已失效'
                            : '确认导入本步'}
                  </Button>
                </Flex>
              );
            })}
          </Flex>
          {activeSection && (
            <Flex vertical gap={8} className="ai-chat-review-card__step">
              {activeSection.issues.length > 0 && (
                <Alert
                  type="warning"
                  showIcon
                  message={`${activeSection.title}：${activeSection.issues.length} 条待处理`}
                  description={
                    <ul className="ai-chat-review__issues">
                      {activeSection.issues.slice(0, 20).map((issue, issueIndex) => (
                        <li key={issueIndex}>{issue}</li>
                      ))}
                    </ul>
                  }
                />
              )}
              <SectionTable section={activeSection} />
              {dependency && (
                <Alert
                  type="warning"
                  showIcon
                  message={
                    dependency.step === -1
                      ? `「${dependency.title}」分表尚未生成或导入，请先确认前置步骤`
                      : `请先确认第 ${dependency.step + 1} 步「${dependency.title}」`
                  }
                />
              )}
              {activeStatus === 'failed' && (
                <Alert type="error" showIcon message="本步导入失败，可重试" />
              )}
              {activeSection.resultSummary && activeStatus === 'submitted' && (
                <Typography.Text type="secondary" className="ai-chat-review-card__step-result">
                  {sectionResultText(activeSection)}
                </Typography.Text>
              )}
            </Flex>
          )}
        </Flex>
      )}
      <Flex justify="space-between" align="center" wrap gap={8} className="ai-chat-review-card__footer">
        <Typography.Text type="secondary">
          共 {allRows} 行，含 {allIssues.length} 条提示
        </Typography.Text>
        {!submitted && !expired && (
          <Popconfirm
            title={`确认导入全部 ${sections.length} 张表？`}
            description={`全部共 ${allRows} 行，将按类型与依赖顺序逐表导入。`}
            okText="确认导入"
            cancelText="取消"
            disabled={submitting || anyRunning || disabled}
            onConfirm={() => onAction?.('review:submit', { reviewId: review.id })}
          >
            <Button
              type="primary"
              loading={submitting}
              disabled={disabled || anyRunning}
            >
              全部确认并入库
            </Button>
          </Popconfirm>
        )}
      </Flex>
      {submitted && <Alert type="success" showIcon message="已确认导入，数据已入库" />}
      {runtime.error && (
        <Alert
          type="error"
          showIcon
          message={runtime.error}
          className="ai-chat-review-card__step-error"
        />
      )}
    </div>
  );
};

export interface DynamicReviewProps {
  review: AiReviewSchema;
  disabled?: boolean;
  messageId?: number;
  onSubmit: (reviewId: string) => void | Promise<void>;
  onConfirmStep?: (
    messageId: number | undefined,
    reviewId: string,
    sectionKey: string,
  ) => AiReviewSchema | Promise<AiReviewSchema> | void;
  onConfirmGroup?: (
    messageId: number | undefined,
    reviewId: string,
    type: AiReviewSectionType,
  ) => AiReviewSchema | Promise<AiReviewSchema> | void;
}

/**
 * Batch-import review card rendered through the official A2UI renderer
 * (@ant-design/x-card). Sections are grouped by business type; each sheet is
 * confirmed independently, the whole type group can be confirmed together, or
 * everything can be confirmed in one flow.
 */
export const DynamicReview: React.FC<DynamicReviewProps> = ({
  review,
  disabled,
  messageId,
  onSubmit,
  onConfirmStep,
  onConfirmGroup,
}) => {
  const [submitting, setSubmitting] = useState(false);
  const [submittingKey, setSubmittingKey] = useState<string | null>(null);
  const [submittingGroup, setSubmittingGroup] = useState(false);
  const [activeKey, setActiveKey] = useState<string | undefined>(undefined);
  const [activeType, setActiveType] = useState<AiReviewSectionType | undefined>(undefined);
  const [localReview, setLocalReview] = useState<AiReviewSchema>(review);
  const [error, setError] = useState<string | null>(null);
  const commandsRef = useRef<XAgentCommand_v0_9[]>([]);
  const [commands, setCommands] = useState<XAgentCommand_v0_9[]>([]);
  const idRef = useRef<string>('');

  useEffect(() => {
    setLocalReview(review);
    const types = SECTION_ORDER.filter((type) =>
      review.sections.some((section) => sectionType(section) === type),
    );
    const preferredType =
      activeType && types.includes(activeType) ? activeType : types[0];
    setActiveType(preferredType);
    setActiveKey((current) =>
      current &&
      review.sections.some(
        (section) => section.key === current && sectionType(section) === preferredType,
      )
        ? current
        : review.sections.find((section) => sectionType(section) === preferredType)?.key,
    );
  }, [activeType, review]);

  useEffect(() => {
    const sid = surfaceId(localReview.id);
    if (idRef.current !== sid) {
      commandsRef.current = [];
      idRef.current = sid;
    }
    const cmds = commandsRef.current;
    if (cmds.length === 0) {
      cmds.push({
        version: 'v0.9',
        createSurface: { surfaceId: sid, catalogId: REVIEW_CATALOG_ID },
      });
    }
    cmds.push({
      version: 'v0.9',
      updateDataModel: {
        surfaceId: sid,
        path: '/review',
        value: {
          ...localReview,
          submitting,
          activeKey,
          activeType,
          submittingKey,
          submittingGroup,
          error,
        },
      },
    });
    cmds.push({
      version: 'v0.9',
      updateComponents: {
        surfaceId: sid,
        components: [
          {
            id: 'root',
            component: 'ReviewPreview',
            review: { path: '/review' },
            disabled: Boolean(disabled),
          },
        ],
      },
    });
    setCommands([...cmds]);
  }, [activeKey, activeType, disabled, error, localReview, submitting, submittingGroup, submittingKey]);

  const handleSubmit = async (reviewId: string) => {
    if (submitting) return;
    setSubmitting(true);
    setError(null);
    try {
      await onSubmit(reviewId);
    } catch (reason) {
      setError(errorMessage(reason));
    } finally {
      setSubmitting(false);
    }
  };

  const handleConfirmStep = async (reviewId: string, sectionKey: string) => {
    if (submittingKey) return;
    setSubmittingKey(sectionKey);
    setError(null);
    try {
      const updated = await onConfirmStep?.(messageId, reviewId, sectionKey);
      if (updated) setLocalReview(updated);
    } catch (reason) {
      setError(errorMessage(reason));
    } finally {
      setSubmittingKey(null);
    }
  };

  const handleConfirmGroup = async (reviewId: string, type: AiReviewSectionType) => {
    if (submittingGroup) return;
    setSubmittingGroup(true);
    setError(null);
    try {
      const updated = await onConfirmGroup?.(messageId, reviewId, type);
      if (updated) setLocalReview(updated);
    } catch (reason) {
      setError(errorMessage(reason));
    } finally {
      setSubmittingGroup(false);
    }
  };

  const handleAction = (payload: ActionPayload) => {
    const context = payload.context ?? {};
    if (payload.name === 'review:submit') {
      const reviewId =
        typeof context.reviewId === 'string' ? context.reviewId : localReview.id;
      void handleSubmit(reviewId);
      return;
    }
    if (payload.name === 'review:selectType') {
      const type = context.type as AiReviewSectionType | undefined;
      if (type && SECTION_ORDER.includes(type)) {
        setActiveType(type);
        setActiveKey(
          localReview.sections.find((section) => sectionType(section) === type)?.key,
        );
      }
      return;
    }
    if (payload.name === 'review:selectStep') {
      if (typeof context.sectionKey === 'string') {
        const section = localReview.sections.find(
          (item) => item.key === context.sectionKey,
        );
        setActiveKey(context.sectionKey);
        if (section) setActiveType(sectionType(section));
      }
      return;
    }
    if (payload.name === 'review:confirmStep') {
      const reviewId =
        typeof context.reviewId === 'string' ? context.reviewId : localReview.id;
      if (typeof context.sectionKey === 'string') {
        void handleConfirmStep(reviewId, context.sectionKey);
      }
      return;
    }
    if (payload.name === 'review:confirmGroup') {
      const reviewId =
        typeof context.reviewId === 'string' ? context.reviewId : localReview.id;
      const type = context.type as AiReviewSectionType | undefined;
      if (type && SECTION_ORDER.includes(type)) {
        void handleConfirmGroup(reviewId, type);
      }
    }
  };

  return (
    <div className="ai-chat-review">
      <XCard.Box
        components={{ ReviewPreview }}
        commands={commands}
        onAction={handleAction}
      >
        <XCard.Card id={surfaceId(localReview.id)} />
      </XCard.Box>
      {error && <Alert type="error" showIcon message={error} className="ai-chat-review__error" />}
    </div>
  );
};

export default DynamicReview;
