```
ERROR in src/pages/SBOM/SBOMInventory.tsx:284:16
TS7006: Parameter '_' implicitly has an 'any' type.
    282 |       title: 'Component',
    283 |       key: 'name',
  > 284 |       render: (_, record) => (
        |                ^
    285 |         <Space direction="vertical" size="small">
    286 |           <Text strong>{record.name}</Text>
    287 |           <Text type="secondary">{record.version}</Text>
ERROR in src/pages/SBOM/SBOMInventory.tsx:284:19
TS7006: Parameter 'record' implicitly has an 'any' type.
    282 |       title: 'Component',
    283 |       key: 'name',
  > 284 |       render: (_, record) => (
        |                   ^^^^^^
    285 |         <Space direction="vertical" size="small">
    286 |           <Text strong>{record.name}</Text>
    287 |           <Text type="secondary">{record.version}</Text>
ERROR in src/pages/SBOM/SBOMInventory.tsx:295:16
TS7006: Parameter 'type' implicitly has an 'any' type.
    293 |       dataIndex: 'component_type',
    294 |       key: 'component_type',
  > 295 |       render: (type) => <Tag>{type}</Tag>
        |                ^^^^
    296 |     },
    297 |     {
    298 |       title: 'License',
ERROR in src/pages/SBOM/SBOMInventory.tsx:306:16
TS7006: Parameter '_' implicitly has an 'any' type.
    304 |       title: 'Vulnerabilities',
    305 |       key: 'vulnerabilities',
  > 306 |       render: (_, record) => {
        |                ^
    307 |         const vulnCount = record.vulnerabilities?.length || 0;
    308 |         if (vulnCount === 0) {
    309 |           return <Tag color="green">Clean</Tag>;
ERROR in src/pages/SBOM/SBOMInventory.tsx:306:19
TS7006: Parameter 'record' implicitly has an 'any' type.
    304 |       title: 'Vulnerabilities',
    305 |       key: 'vulnerabilities',
  > 306 |       render: (_, record) => {
        |                   ^^^^^^
    307 |         const vulnCount = record.vulnerabilities?.length || 0;
    308 |         if (vulnCount === 0) {
    309 |           return <Tag color="green">Clean</Tag>;
ERROR in src/pages/SBOM/SBOMInventory.tsx:312:56
TS7006: Parameter 'v' implicitly has an 'any' type.
    310 |         }
    311 |         
  > 312 |         const critical = record.vulnerabilities.filter(v => v.severity === 'critical').length;
        |                                                        ^
    313 |         const high = record.vulnerabilities.filter(v => v.severity === 'high').length;
    314 |         
    315 |         return (
ERROR in src/pages/SBOM/SBOMInventory.tsx:313:52
TS7006: Parameter 'v' implicitly has an 'any' type.
    311 |         
    312 |         const critical = record.vulnerabilities.filter(v => v.severity === 'critical').length;
  > 313 |         const high = record.vulnerabilities.filter(v => v.severity === 'high').length;
        |                                                    ^
    314 |         
    315 |         return (
    316 |           <Space>
ERROR in src/pages/SBOM/SBOMInventory.tsx:331:16
TS7006: Parameter 'purl' implicitly has an 'any' type.
    329 |       key: 'purl',
    330 |       ellipsis: true,
  > 331 |       render: (purl) => (
        |                ^^^^
    332 |         <Tooltip title={purl}>
    333 |           <Text code style={{ fontSize: 12 }}>{purl}</Text>
    334 |         </Tooltip>

// src/pages/SBOM/SBOMInventory.tsx
import React, { useState, useEffect } from 'react';
import {
  Card, Table, Button, Upload, Tag, Space,
  Modal, Tree, Descriptions, Badge, Alert,
  Tabs, Typography, Progress, Tooltip, Drawer,
  List, Row, Col, Statistic, message
} from 'antd';
import {
  UploadOutlined, FileTextOutlined,
  ContainerOutlined, AppstoreOutlined,
  SecurityScanOutlined, WarningOutlined
} from '@ant-design/icons';
import { sbomAPI } from '../../services/api';
import { getSeverityColor } from '../../utils/helpers';
import moment from 'moment';

const { TabPane } = Tabs;
const { Text, Link } = Typography;

const SBOMInventory: React.FC = () => {
  const [uploadModal, setUploadModal] = useState(false);
  const [selectedSBOM, setSelectedSBOM] = useState<any>(null);
  const [componentDrawer, setComponentDrawer] = useState(false);
  const [sbomList, setSbomList] = useState<any[]>([]);
  const [loading, setLoading] = useState(false);

  useEffect(() => {
    fetchSBOMList();
  }, []);

  const fetchSBOMList = async () => {
    setLoading(true);
    try {
      const response = await sbomAPI.getSBOMs({});
      setSbomList(response.data);
    } catch (error) {
      console.error('Failed to fetch SBOM list:', error);
      message.error('Failed to fetch SBOM inventory');
    } finally {
      setLoading(false);
    }
  };

  const showVulnerabilities = (sbom: any) => {
    setSelectedSBOM(sbom);
    setComponentDrawer(true);
  };

  const viewSBOM = (sbom: any) => {
    setSelectedSBOM(sbom);
    setComponentDrawer(true);
  };

  const scanSBOM = async (sbom: any) => {
    try {
      await sbomAPI.scanSBOM(sbom.sbom_id);
      message.success('SBOM scan initiated');
      fetchSBOMList(); // Refresh the list
    } catch (error) {
      message.error('Failed to scan SBOM');
    }
  };

  const handleSBOMUpload = async (options: any) => {
    const { file, onSuccess, onError } = options;
    
    try {
      const metadata = {
        asset_id: 1, // This should come from a form or selection
        source_type: 'application',
        source_identifier: file.name
      };
      
      await sbomAPI.uploadSBOM(file, metadata);
      message.success('SBOM uploaded successfully');
      onSuccess();
      setUploadModal(false);
      fetchSBOMList();
    } catch (error) {
      message.error('Failed to upload SBOM');
      onError(error);
    }
  };

  const handleUploadChange = (info: any) => {
    if (info.file.status === 'done') {
      message.success(`${info.file.name} file uploaded successfully`);
    } else if (info.file.status === 'error') {
      message.error(`${info.file.name} file upload failed.`);
    }
  };

  const getFormatColor = (format: string) => {
    const colors: Record<string, string> = {
      CycloneDX: 'blue',
      SPDX: 'green',
      SWID: 'orange',
      other: 'default'
    };
    return colors[format] || 'default';
  };

  const columns = [
    {
      title: 'Asset',
      key: 'asset',
      render: (_: any, record: any) => (
        <Space>
          <Text strong>{record.asset?.hostname || 'Unknown'}</Text>
          <Text type="secondary">({record.asset?.ip_address || 'N/A'})</Text>
        </Space>
      )
    },
    {
      title: 'Format',
      dataIndex: 'sbom_format',
      key: 'sbom_format',
      render: (format: string) => (
        <Tag color={getFormatColor(format)}>{format}</Tag>
      )
    },
    {
      title: 'Source',
      key: 'source',
      render: (_: any, record: any) => (
        <Space>
          {record.source_type === 'container' ? (
            <ContainerOutlined />
          ) : (
            <AppstoreOutlined />
          )}
          <Text>{record.source_identifier}</Text>
        </Space>
      )
    },
    {
      title: 'Components',
      key: 'components',
      render: (_: any, record: any) => (
        <Badge count={record.component_count || 0} showZero>
          <Tag>Components</Tag>
        </Badge>
      )
    },
    {
      title: 'Vulnerabilities',
      key: 'vulnerabilities',
      render: (_: any, record: any) => (
        <Space>
          {(record.critical_vulns || 0) > 0 && (
            <Tag color="red">{record.critical_vulns} Critical</Tag>
          )}
          {(record.high_vulns || 0) > 0 && (
            <Tag color="orange">{record.high_vulns} High</Tag>
          )}
          {(record.total_vulns || 0) > 0 && (
            <Tooltip title="Click to view details">
              <Button
                size="small"
                danger
                onClick={() => showVulnerabilities(record)}
              >
                View All ({record.total_vulns})
              </Button>
            </Tooltip>
          )}
        </Space>
      )
    },
    {
      title: 'Uploaded',
      key: 'uploaded',
      render: (_: any, record: any) => (
        <Space direction="vertical" size="small">
          <Text>{moment(record.created_at).format('YYYY-MM-DD')}</Text>
          <Text type="secondary">by {record.uploaded_by?.full_name || 'Unknown'}</Text>
        </Space>
      )
    },
    {
      title: 'Actions',
      key: 'actions',
      render: (_: any, record: any) => (
        <Space>
          <Button
            icon={<FileTextOutlined />}
            size="small"
            onClick={() => viewSBOM(record)}
          >
            View
          </Button>
          <Button
            icon={<SecurityScanOutlined />}
            size="small"
            onClick={() => scanSBOM(record)}
          >
            Scan
          </Button>
        </Space>
      )
    }
  ];

  return (
    <Card
      title="SBOM Inventory"
      extra={
        <Button
          type="primary"
          icon={<UploadOutlined />}
          onClick={() => setUploadModal(true)}
        >
          Upload SBOM
        </Button>
      }
    >
      <Alert
        message="Software Bill of Materials (SBOM) Management"
        description="Track and analyze components in your software supply chain. Upload SBOM files in CycloneDX, SPDX, or SWID formats."
        type="info"
        showIcon
        style={{ marginBottom: 16 }}
      />

      <Table
        columns={columns}
        dataSource={sbomList}
        loading={loading}
        rowKey="sbom_id"
        pagination={{
          pageSize: 20,
          showSizeChanger: true
        }}
      />

      <Modal
        title="Upload SBOM"
        visible={uploadModal}
        onCancel={() => setUploadModal(false)}
        footer={null}
        width={600}
      >
        <Upload.Dragger
          name="sbom"
          multiple={false}
          accept=".json,.xml,.spdx,.cdx"
          customRequest={handleSBOMUpload}
          onChange={handleUploadChange}
        >
          <p className="ant-upload-drag-icon">
            <UploadOutlined />
          </p>
          <p className="ant-upload-text">
            Click or drag SBOM file to this area to upload
          </p>
          <p className="ant-upload-hint">
            Support for CycloneDX, SPDX, and SWID formats
          </p>
        </Upload.Dragger>
      </Modal>

      <SBOMDetailDrawer
        visible={componentDrawer}
        sbom={selectedSBOM}
        onClose={() => setComponentDrawer(false)}
      />
    </Card>
  );
};

// Компонент для отображения деталей SBOM
const SBOMDetailDrawer: React.FC<{ sbom: any; visible: boolean; onClose: () => void }> = ({
  sbom,
  visible,
  onClose
}) => {
  const [selectedComponent, setSelectedComponent] = useState(null);

  const componentColumns = [
    {
      title: 'Component',
      key: 'name',
      render: (_, record) => (
        <Space direction="vertical" size="small">
          <Text strong>{record.name}</Text>
          <Text type="secondary">{record.version}</Text>
        </Space>
      )
    },
    {
      title: 'Type',
      dataIndex: 'component_type',
      key: 'component_type',
      render: (type) => <Tag>{type}</Tag>
    },
    {
      title: 'License',
      dataIndex: 'license_expression',
      key: 'license_expression',
      ellipsis: true
    },
    {
      title: 'Vulnerabilities',
      key: 'vulnerabilities',
      render: (_, record) => {
        const vulnCount = record.vulnerabilities?.length || 0;
        if (vulnCount === 0) {
          return <Tag color="green">Clean</Tag>;
        }
        
        const critical = record.vulnerabilities.filter(v => v.severity === 'critical').length;
        const high = record.vulnerabilities.filter(v => v.severity === 'high').length;
        
        return (
          <Space>
            {critical > 0 && <Tag color="red">{critical} Critical</Tag>}
            {high > 0 && <Tag color="orange">{high} High</Tag>}
            <Button size="small" onClick={() => setSelectedComponent(record)}>
              View
            </Button>
          </Space>
        );
      }
    },
    {
      title: 'PURL',
      dataIndex: 'purl',
      key: 'purl',
      ellipsis: true,
      render: (purl) => (
        <Tooltip title={purl}>
          <Text code style={{ fontSize: 12 }}>{purl}</Text>
        </Tooltip>
      )
    }
  ];

  return (
    <Drawer
      title="SBOM Details"
      placement="right"
      width={1000}
      visible={visible}
      onClose={onClose}
    >
      {sbom && (
        <>
          <Descriptions bordered style={{ marginBottom: 24 }}>
            <Descriptions.Item label="Format">{sbom.sbom_format}</Descriptions.Item>
            <Descriptions.Item label="Version">{sbom.sbom_version}</Descriptions.Item>
            <Descriptions.Item label="Source">{sbom.source_identifier}</Descriptions.Item>
            <Descriptions.Item label="Components">{sbom.components?.length || 0}</Descriptions.Item>
            <Descriptions.Item label="Created">{moment(sbom.created_at).format('YYYY-MM-DD HH:mm')}</Descriptions.Item>
            <Descriptions.Item label="Asset">{sbom.asset.hostname}</Descriptions.Item>
          </Descriptions>

          <Tabs defaultActiveKey="components">
            <TabPane tab="Components" key="components">
              <Table
                columns={componentColumns}
                dataSource={sbom.components}
                pagination={{
                  pageSize: 50,
                  showSizeChanger: true
                }}
              />
            </TabPane>
            
            <TabPane tab="Dependency Tree" key="tree">
              <Tree
                treeData={buildDependencyTree(sbom.components)}
                showLine
                showIcon
                defaultExpandAll
              />
            </TabPane>
            
            <TabPane tab="Vulnerabilities" key="vulnerabilities">
              <SBOMVulnerabilities sbom={sbom} />
            </TabPane>
            
            <TabPane tab="Licenses" key="licenses">
              <LicenseAnalysis components={sbom.components} />
            </TabPane>
          </Tabs>
        </>
      )}
    </Drawer>
  );
};

const SBOMVulnerabilities: React.FC<{ sbom: any }> = ({ sbom }) => {
  const [vulnerabilities, setVulnerabilities] = useState<any[]>([]);
  const [loading, setLoading] = useState(false);

  useEffect(() => {
    if (sbom) {
      fetchVulnerabilities();
    }
  }, [sbom]);

  const fetchVulnerabilities = async () => {
    setLoading(true);
    try {
      const response = await sbomAPI.getSBOMVulnerabilities(sbom.sbom_id);
      setVulnerabilities(response.data);
    } catch (error) {
      console.error('Failed to fetch SBOM vulnerabilities:', error);
    } finally {
      setLoading(false);
    }
  };

  const columns = [
    {
      title: 'Component',
      key: 'component',
      render: (_: any, record: any) => (
        <Space direction="vertical" size="small">
          <Text strong>{record.component.name}</Text>
          <Text type="secondary">{record.component.version}</Text>
        </Space>
      ),
    },
    {
      title: 'Vulnerability',
      key: 'vulnerability',
      render: (_: any, record: any) => (
        <Space direction="vertical" size="small">
          <Tag>{record.vulnerability.cve_id || record.vulnerability.title}</Tag>
          <Text type="secondary" ellipsis style={{ width: 200 }}>
            {record.vulnerability.description}
          </Text>
        </Space>
      ),
    },
    {
      title: 'Severity',
      key: 'severity',
      render: (_: any, record: any) => (
        <Tag color={getSeverityColor(record.vulnerability.severity)}>
          {record.vulnerability.severity.toUpperCase()}
        </Tag>
      ),
    },
    {
      title: 'CVSS Score',
      key: 'cvss',
      render: (_: any, record: any) => record.vulnerability.cvss_v3_score || 'N/A',
    },
    {
      title: 'Match Type',
      dataIndex: 'match_type',
      key: 'match_type',
      render: (type: string) => <Tag>{type.toUpperCase()}</Tag>,
    },
    {
      title: 'Confidence',
      dataIndex: 'confidence_score',
      key: 'confidence_score',
      render: (score: number) => (
        <Progress
          percent={score}
          size="small"
          strokeColor={score >= 90 ? '#52c41a' : score >= 70 ? '#faad14' : '#ff4d4f'}
        />
      ),
    },
  ];

  return (
    <Table
      columns={columns}
      dataSource={vulnerabilities}
      loading={loading}
      pagination={{
        pageSize: 20,
        showSizeChanger: true,
      }}
    />
  );
};

const LicenseAnalysis: React.FC<{ components: any[] }> = ({ components }) => {
  const [licenseStats, setLicenseStats] = useState<any>({});

  useEffect(() => {
    analyzeLicenses();
  }, [components]);
/*
  const analyzeLicenses = () => {
    const stats: any = {};
    const licenseRisks: any = {
      high: ['GPL', 'AGPL', 'LGPL', 'GPL-2.0', 'GPL-3.0', 'AGPL-3.0'],
      medium: ['MPL', 'EPL', 'CDDL', 'MPL-2.0', 'EPL-2.0'],
      low: ['MIT', 'Apache-2.0', 'BSD', 'ISC', 'BSD-3-Clause', 'BSD-2-Clause'],
    };

    components.forEach(component => {
      const license = component.license_expression || 'Unknown';
      stats[license] = (stats[license] || 0) + 1;
    });

    setLicenseStats(stats);
  };
*/
  const analyzeLicenses = () => {
    const stats: any = {};
    components.forEach(component => {
      const license = component.license_expression || 'Unknown';
      stats[license] = (stats[license] || 0) + 1;
    });
    setLicenseStats(stats);
  };


  const getLicenseRisk = (license: string): string => {
    const licenseUpper = license.toUpperCase();
    if (['GPL', 'AGPL', 'LGPL'].some(l => licenseUpper.includes(l))) return 'high';
    if (['MPL', 'EPL', 'CDDL'].some(l => licenseUpper.includes(l))) return 'medium';
    return 'low';
  };

  const getLicenseColor = (risk: string): string => {
    switch (risk) {
      case 'high': return '#ff4d4f';
      case 'medium': return '#faad14';
      case 'low': return '#52c41a';
      default: return '#d9d9d9';
    }
  };

  const licenseData = Object.entries(licenseStats).map(([license, count]) => ({
    license,
    count: count as number,
    risk: getLicenseRisk(license),
  }));

  const columns = [
    {
      title: 'License',
      dataIndex: 'license',
      key: 'license',
      render: (license: string) => <Text strong>{license}</Text>,
    },
    {
      title: 'Components',
      dataIndex: 'count',
      key: 'count',
      render: (count: number) => <Badge count={count} showZero />,
    },
    {
      title: 'Risk Level',
      dataIndex: 'risk',
      key: 'risk',
      render: (risk: string) => (
        <Tag color={getLicenseColor(risk)}>
          {risk.toUpperCase()}
        </Tag>
      ),
    },
    {
      title: 'Percentage',
      key: 'percentage',
      render: (_: any, record: any) => {
        const percentage = (record.count / components.length) * 100;
        return (
          <Progress
            percent={percentage}
            size="small"
            format={(percent) => `${percent?.toFixed(1)}%`}
          />
        );
      },
    },
  ];

  const riskSummary = {
    high: licenseData.filter(l => l.risk === 'high').reduce((sum, l) => sum + l.count, 0),
    medium: licenseData.filter(l => l.risk === 'medium').reduce((sum, l) => sum + l.count, 0),
    low: licenseData.filter(l => l.risk === 'low').reduce((sum, l) => sum + l.count, 0),
  };

  return (
    <Space direction="vertical" style={{ width: '100%' }} size="large">
      <Row gutter={[16, 16]}>
        <Col span={8}>
          <Card>
            <Statistic
              title="High Risk Licenses"
              value={riskSummary.high}
              valueStyle={{ color: '#ff4d4f' }}
              suffix={`/ ${components.length}`}
            />
          </Card>
        </Col>
        <Col span={8}>
          <Card>
            <Statistic
              title="Medium Risk Licenses"
              value={riskSummary.medium}
              valueStyle={{ color: '#faad14' }}
              suffix={`/ ${components.length}`}
            />
          </Card>
        </Col>
        <Col span={8}>
          <Card>
            <Statistic
              title="Low Risk Licenses"
              value={riskSummary.low}
              valueStyle={{ color: '#52c41a' }}
              suffix={`/ ${components.length}`}
            />
          </Card>
        </Col>
      </Row>

      <Table
        columns={columns}
        dataSource={licenseData}
        pagination={false}
        summary={() => (
          <Table.Summary>
            <Table.Summary.Row>
              <Table.Summary.Cell index={0}>
                <Text strong>Total</Text>
              </Table.Summary.Cell>
              <Table.Summary.Cell index={1}>
                <Text strong>{components.length}</Text>
              </Table.Summary.Cell>
              <Table.Summary.Cell index={2} colSpan={2} />
            </Table.Summary.Row>
          </Table.Summary>
        )}
      />

      <Alert
        message="License Compliance"
        description={
          <Space direction="vertical">
            <Text>
              High-risk licenses (GPL, AGPL, LGPL) may require you to open-source your code.
            </Text>
            <Text>
              Medium-risk licenses (MPL, EPL, CDDL) have specific requirements for distribution.
            </Text>
            <Text>
              Low-risk licenses (MIT, Apache, BSD) are generally permissive for commercial use.
            </Text>
          </Space>
        }
        type="info"
        showIcon
      />
    </Space>
  );
};

// Helper function to build dependency tree
const buildDependencyTree = (components: any[]): any[] => {
  // This is a simplified version - in a real app, you'd build a proper tree structure
  return components.map(component => ({
    title: `${component.name} (${component.version})`,
    key: component.component_id,
    children: component.dependencies?.map((dep: any) => ({
      title: `${dep.name} (${dep.version})`,
      key: `${component.component_id}-${dep.name}`,
      isLeaf: true,
    })) || [],
  }));
};

export default SBOMInventory;