/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import { EChart } from '@/components/eChart/eChart';
import { GraphLegendIcon } from '@/utils/themeIcons';
import { cardHeadStyle, statisticValueStyle } from '@/v2/pages/capacity/constants/styles.constants';
import CapacityDetailError from '@/v2/pages/capacity/components/CapacityDetailError';
import { Segment } from '@/v2/types/capacity.types';
import { DownloadOutlined } from '@ant-design/icons';
import { Card, Divider, Row, Select, Spin, Statistic } from 'antd';
import filesize from 'filesize';
import React from 'react';

type DataDetailItem = {
  title: string | React.ReactNode;
  size: number;
  breakdown: Segment[];
  loading?: boolean;
  hasError?: boolean;
  errorMessage?: string;
  errorTestId?: string;
}

type CapacityDetailProps = {
  title: string | React.ReactNode;
  showDropdown: boolean;
  selectorTitle?: string | React.ReactNode;
  dataDetails: DataDetailItem[];
  downloadUrl?: string;
  dropdownItems?: {
    label: React.ReactNode | string;
    value: string;
  }[];
  onDownloadClick?: () => void;
  disabledOpts?: string[];
  optsClass?: string;
  handleSelect?: React.Dispatch<React.SetStateAction<string>>
  loading: boolean;
  extra?: React.ReactNode;
};

const getEchartOptions = (title: string | React.ReactNode, data: DataDetailItem) => {
  const option = {
    grid: {
      left: 2,
      right: 4,
      top: 16,
      bottom: 0
    },
    xAxis: {
      // Use linear scale to support zero values safely
      type: 'value',
      axisLine: { show: false },
      axisTick: { show: false },
      axisLabel: { show: false }
    },
    yAxis: {
      type: 'category',
      axisLine: { show: false },
      axisTick: { show: false },
      axisLabel: { show: false },
    },
  };

  const breakdownLen = data.breakdown.length;
  const series = data.breakdown.map((breakdown, idx) => ({
    type: 'bar',
    ...(breakdownLen > 1 && { stack: title }),
    itemStyle: {
      ...(idx === breakdownLen - 1 && { borderRadius: [0, 50, 50, 0] }),
      ...(idx === 0 && { borderRadius: [50, 0, 0, 50] }),
      ...(breakdownLen === 1 && { borderRadius: [50, 50, 50, 50] }),
      color: breakdown.color,
    },
    data: [breakdown.value],
    barWidth: '10px',
    barGap: '2px'
  }));

  return {
    ...option,
    series
  } as any
}


const CapacityDetail: React.FC<CapacityDetailProps> = (
  {
    title,
    showDropdown,
    selectorTitle,
    downloadUrl,
    dropdownItems,
    onDownloadClick,
    disabledOpts,
    optsClass,
    dataDetails,
    handleSelect,
    loading,
    extra
  }
) => {

  const options = dropdownItems?.map((item) => ({
    label: item.label,
    value: item.value,
    ...(disabledOpts?.includes(item.value) && { disabled: true }),
    ...(optsClass && { className: optsClass }),
  })) ?? [];

  const cardExtra = extra ?? (downloadUrl
    ? (
      <a
        href={downloadUrl}
        onClick={(event) => {
          if (onDownloadClick) {
            event.preventDefault();
            onDownloadClick();
          }
        }}
        rel='noopener noreferrer'
      >
        Download Insights <DownloadOutlined />
      </a>
    )
    : undefined);

  return (
    <Card title={title} size='small' headStyle={cardHeadStyle} extra={cardExtra}>
      <Spin spinning={loading}>
          <>
            { showDropdown && options.length > 0 &&
              <div className='node-select-container'>
                {selectorTitle}
                <Select
                  showSearch
                  defaultValue={options?.[0]?.value}
                  options={options}
                  onChange={handleSelect}
                  style={{ marginBottom: '16px' }}
                />
              </div>
            }
            <div className='cluster-card-data-container vertical-layout'>
              {dataDetails.map((data, idx) => {
                const size = filesize(data.size, { round: 1 }).split(' ');
                return (
                  <div key={`data-detail-${data.title}-${idx}`} className='data-detail-item'>
                    <Statistic
                      title={data.title}
                      value={data.hasError ? 'N/A' : size[0]}
                      suffix={data.hasError ? undefined : size[1]}
                      valueStyle={statisticValueStyle}
                      className='data-detail-statistic'
                      loading={data.loading}
                    />
                    {!data.loading
                      && (
                        data.hasError
                          ? (
                            <>
                              <CapacityDetailError
                                message={data.errorMessage}
                                testId={data.errorTestId}
                              />
                              {idx < dataDetails.length - 1 && <Divider />}
                            </>
                          )
                          : (
                            <Row className='data-detail-breakdown-container'>
                              {data.breakdown.map((item, idx) => (
                                <div key={`data-defailt-breakdown-${item.label}-${idx}`} className='data-detail-breakdown-item'>
                                  <GraphLegendIcon color={item.color} height={12} />
                                  <span className="data-detail-breakdown-label">{item.label}</span>
                                  <span className="data-detail-breakdown-value">{filesize(item.value, {round: 1})}</span>
                                </div>
                              ))}
                              <EChart
                                option={getEchartOptions(data.title, data)}
                                style={{ height: '40px', width: '100%', margin: '10px 0px' }} />
                              {idx < dataDetails.length - 1 && <Divider />}
                            </Row>
                          )
                      )}
                  </div>
                )
              })}
            </div>
          </>
        </Spin>
    </Card>
  );
}

export default CapacityDetail;
