/**
 * GenUI API 契约测试
 * 验证 GenUI 返回的 ui_schema 符合前端类型定义
 */
import { describe, it, expect } from 'vitest';
import type { 
  UISchema, 
  UIComponent, 
  ComponentType,
  StatItem,
  TableColumn,
  ActionButton,
  ChartDataPoint
} from '../types';

// ========== 模拟后端响应数据 ==========
const mockDashboardResponse: UISchema = {
  layout: 'vertical',
  gap: 'md',
  components: [
    {
      type: 'stats_row',
      id: 'overview-stats',
      props: {
        items: [
          { label: '本月营收', value: '¥125,000', color: 'success', trend: '+12%' },
          { label: '待处理订单', value: '15单', color: 'warning' },
        ],
        columns: 4
      }
    },
    {
      type: 'chart',
      id: 'sales-trend',
      props: {
        title: '销售趋势',
        type: 'area',
        data: [
          { label: '1/1', value: 1000 },
          { label: '1/2', value: 1500 },
        ],
        xKey: 'label',
        yKey: 'value',
        height: 200
      }
    },
    {
      type: 'container',
      props: {
        layout: 'horizontal',
        gap: 'md',
        children: [
          {
            type: 'data_table',
            props: {
              title: '低库存商品',
              columns: [
                { key: 'name', label: '商品名称' },
                { key: 'stock', label: '库存' }
              ],
              data: [
                { id: '1', name: '商品A', stock: 5 },
                { id: '2', name: '商品B', stock: 3 },
              ]
            }
          },
          {
            type: 'alert',
            props: {
              type: 'warning',
              title: '库存预警',
              description: '有5件商品库存不足'
            }
          }
        ]
      }
    }
  ]
};

const mockInsightFeedResponse: UISchema = {
  layout: 'vertical',
  gap: 'sm',
  components: [
    {
      type: 'insight_feed',
      props: {
        title: '运营洞察',
        insights: [
          {
            id: 'insight-1',
            type: 'opportunity',
            title: '销售增长机会',
            description: '周末流量预计增加30%',
            priority: 'high',
            actionLabel: '查看详情',
            actionId: 'view_detail'
          },
          {
            id: 'insight-2',
            type: 'warning',
            title: '库存预警',
            description: '3件商品即将售罄',
            priority: 'urgent'
          }
        ],
        layout: 'list',
        groupBy: 'priority'
      }
    }
  ]
};

const mockApprovalListResponse: UISchema = {
  layout: 'vertical',
  gap: 'md',
  components: [
    {
      type: 'approval_list',
      props: {
        title: '待审批事项',
        approvals: [
          {
            id: 'approval-1',
            type: 'marketing',
            title: '春节促销活动',
            description: '满减活动，预算5万',
            agent: 'marketing',
            priority: 'high',
            amount: 50000,
            timestamp: '2024-01-15T10:00:00Z'
          }
        ],
        layout: 'cards',
        showActions: true
      }
    }
  ]
};

// ========== 类型验证辅助函数 ==========
function isValidComponentType(type: string): type is ComponentType {
  const validTypes: ComponentType[] = [
    'stats_row', 'data_table', 'chart', 'alert', 'action_buttons',
    'approval_card', 'insight_card', 'progress_bar', 'text', 'divider',
    'container', 'agent_status', 'agent_capabilities', 'agent_thinking',
    'agent_settings_card', 'agent_settings_list', 'sandbox_result',
    'insight_feed', 'approval_list'
  ];
  return validTypes.includes(type as ComponentType);
}

function validateUISchema(schema: unknown): schema is UISchema {
  if (!schema || typeof schema !== 'object') return false;
  const s = schema as Record<string, unknown>;
  
  if (!['vertical', 'horizontal', 'grid'].includes(s.layout as string)) return false;
  if (!['sm', 'md', 'lg'].includes(s.gap as string)) return false;
  if (!Array.isArray(s.components)) return false;
  
  return true;
}

function validateComponent(component: unknown): component is UIComponent {
  if (!component || typeof component !== 'object') return false;
  const c = component as Record<string, unknown>;
  
  if (typeof c.type !== 'string') return false;
  if (!isValidComponentType(c.type)) return false;
  if (!c.props || typeof c.props !== 'object') return false;
  
  return true;
}

// ========== 测试套件 ==========
describe('GenUI API 契约测试', () => {
  
  describe('UISchema 顶层结构', () => {
    it('应验证有效的layout值', () => {
      expect(validateUISchema({ layout: 'vertical', gap: 'md', components: [] })).toBe(true);
      expect(validateUISchema({ layout: 'horizontal', gap: 'sm', components: [] })).toBe(true);
      expect(validateUISchema({ layout: 'grid', gap: 'lg', components: [] })).toBe(true);
      expect(validateUISchema({ layout: 'invalid', gap: 'md', components: [] })).toBe(false);
    });

    it('应验证有效的gap值', () => {
      expect(validateUISchema({ layout: 'vertical', gap: 'sm', components: [] })).toBe(true);
      expect(validateUISchema({ layout: 'vertical', gap: 'md', components: [] })).toBe(true);
      expect(validateUISchema({ layout: 'vertical', gap: 'lg', components: [] })).toBe(true);
      expect(validateUISchema({ layout: 'vertical', gap: 'xl', components: [] })).toBe(false);
    });

    it('应要求components为数组', () => {
      expect(validateUISchema({ layout: 'vertical', gap: 'md', components: [] })).toBe(true);
      expect(validateUISchema({ layout: 'vertical', gap: 'md', components: null })).toBe(false);
      expect(validateUISchema({ layout: 'vertical', gap: 'md' })).toBe(false);
    });
  });

  describe('组件类型白名单', () => {
    it('应接受所有有效的组件类型', () => {
      const validTypes: ComponentType[] = [
        'stats_row', 'data_table', 'chart', 'alert', 'action_buttons',
        'approval_card', 'insight_card', 'progress_bar', 'text', 'divider',
        'container', 'agent_status', 'agent_capabilities', 'agent_thinking',
        'agent_settings_card', 'agent_settings_list', 'sandbox_result',
        'insight_feed', 'approval_list'
      ];

      validTypes.forEach(type => {
        expect(isValidComponentType(type)).toBe(true);
      });
    });

    it('应拒绝无效的组件类型', () => {
      expect(isValidComponentType('invalid_type')).toBe(false);
      expect(isValidComponentType('button')).toBe(false);
      expect(isValidComponentType('modal')).toBe(false);
    });
  });

  describe('Dashboard响应契约', () => {
    it('应验证完整的dashboard响应', () => {
      expect(validateUISchema(mockDashboardResponse)).toBe(true);
    });

    it('所有组件应符合类型定义', () => {
      function validateAllComponents(components: unknown[]): boolean {
        for (const comp of components) {
          if (!validateComponent(comp)) return false;
          
          const c = comp as UIComponent;
          if (c.type === 'container') {
            const children = (c.props as { children?: unknown[] }).children;
            if (children && !validateAllComponents(children)) return false;
          }
        }
        return true;
      }

      expect(validateAllComponents(mockDashboardResponse.components)).toBe(true);
    });

    it('stats_row组件应包含items数组', () => {
      const statsRow = mockDashboardResponse.components.find(c => c.type === 'stats_row');
      expect(statsRow).toBeDefined();
      
      const items = (statsRow?.props as { items?: StatItem[] }).items;
      expect(Array.isArray(items)).toBe(true);
      expect(items?.[0]).toHaveProperty('label');
      expect(items?.[0]).toHaveProperty('value');
    });

    it('chart组件应包含type和data', () => {
      const chart = mockDashboardResponse.components.find(c => c.type === 'chart');
      expect(chart).toBeDefined();
      
      const props = chart?.props as { type?: string; data?: ChartDataPoint[] };
      expect(['bar', 'line', 'pie', 'area']).toContain(props.type);
      expect(Array.isArray(props.data)).toBe(true);
    });
  });

  describe('InsightFeed响应契约', () => {
    it('应验证insight_feed组件结构', () => {
      expect(validateUISchema(mockInsightFeedResponse)).toBe(true);
      
      const insightFeed = mockInsightFeedResponse.components.find(c => c.type === 'insight_feed');
      expect(insightFeed).toBeDefined();
    });

    it('insights数组项应有必要字段', () => {
      const insightFeed = mockInsightFeedResponse.components.find(c => c.type === 'insight_feed');
      const insights = (insightFeed?.props as { insights?: unknown[] }).insights;
      
      expect(Array.isArray(insights)).toBe(true);
      if (insights && insights.length > 0) {
        const insight = insights[0] as Record<string, unknown>;
        expect(insight).toHaveProperty('id');
        expect(insight).toHaveProperty('type');
        expect(insight).toHaveProperty('title');
        expect(insight).toHaveProperty('description');
      }
    });
  });

  describe('ApprovalList响应契约', () => {
    it('应验证approval_list组件结构', () => {
      expect(validateUISchema(mockApprovalListResponse)).toBe(true);
      
      const approvalList = mockApprovalListResponse.components.find(c => c.type === 'approval_list');
      expect(approvalList).toBeDefined();
    });

    it('approvals数组项应有必要字段', () => {
      const approvalList = mockApprovalListResponse.components.find(c => c.type === 'approval_list');
      const approvals = (approvalList?.props as { approvals?: unknown[] }).approvals;
      
      expect(Array.isArray(approvals)).toBe(true);
      if (approvals && approvals.length > 0) {
        const approval = approvals[0] as Record<string, unknown>;
        expect(approval).toHaveProperty('id');
        expect(approval).toHaveProperty('type');
        expect(approval).toHaveProperty('title');
        expect(approval).toHaveProperty('agent');
        expect(approval).toHaveProperty('priority');
      }
    });
  });

  describe('Container嵌套验证', () => {
    it('container的children应符合组件类型', () => {
      const container = mockDashboardResponse.components.find(c => c.type === 'container');
      expect(container).toBeDefined();
      
      const children = (container?.props as { children?: UIComponent[] }).children;
      expect(Array.isArray(children)).toBe(true);
      
      children?.forEach(child => {
        expect(validateComponent(child)).toBe(true);
      });
    });

    it('应支持多层嵌套', () => {
      const nestedSchema: UISchema = {
        layout: 'vertical',
        gap: 'md',
        components: [
          {
            type: 'container',
            props: {
              layout: 'horizontal',
              children: [
                {
                  type: 'container',
                  props: {
                    layout: 'vertical',
                    children: [
                      { type: 'text', props: { content: '深层嵌套文本' } }
                    ]
                  }
                }
              ]
            }
          }
        ]
      };

      expect(validateUISchema(nestedSchema)).toBe(true);
    });
  });

  describe('Props类型安全', () => {
    it('data_table的columns应有key和label', () => {
      const container = mockDashboardResponse.components.find(c => c.type === 'container');
      const children = (container?.props as { children?: UIComponent[] }).children;
      const table = children?.find(c => c.type === 'data_table');
      
      const columns = (table?.props as { columns?: TableColumn[] }).columns;
      expect(Array.isArray(columns)).toBe(true);
      columns?.forEach(col => {
        expect(col).toHaveProperty('key');
        expect(col).toHaveProperty('label');
      });
    });

    it('action_buttons的buttons应有label和action', () => {
      const mockButtons: UIComponent = {
        type: 'action_buttons',
        props: {
          buttons: [
            { id: '1', label: '确认', action: 'confirm', variant: 'default' },
            { id: '2', label: '取消', action: 'cancel', variant: 'outline' }
          ]
        }
      };

      expect(validateComponent(mockButtons)).toBe(true);
      const buttons = (mockButtons.props as { buttons?: ActionButton[] }).buttons;
      buttons?.forEach(btn => {
        expect(btn).toHaveProperty('id');
        expect(btn).toHaveProperty('label');
        expect(btn).toHaveProperty('action');
      });
    });
  });
});
