import React, { useState, useMemo, useEffect } from 'react';
import PropTypes from 'prop-types';
import CapRow from '@capillarytech/cap-ui-library/CapRow';
import CapButton from '@capillarytech/cap-ui-library/CapButton';
import CapIcon from '@capillarytech/cap-ui-library/CapIcon';
import CapLabel from '@capillarytech/cap-ui-library/CapLabel';
import CapTab from '@capillarytech/cap-ui-library/CapTab';
import CapTooltip from '@capillarytech/cap-ui-library/CapTooltip';
import {
  FormattedMessage,
  injectIntl,
} from 'react-intl';
import './style.scss';
import messages from './messages';
import { processErrors } from './utils';
import ErrorTypeRenderer from './ErrorTypeRenderer';
import { ANDROID, GENERIC, IOS } from '../../v2Containers/CreativesContainer/constants';
import { ERROR_TAB_KEYS } from '../HtmlEditor/utils/validationConstants';
import { SEVERITY } from '../HtmlEditor/components/ValidationPanel/constants';
import { LIQUID_DOC_URL } from './constants';

const { CapLabelInline } = CapLabel;

/**
 * Group messages into Errors (blocking) and Warnings (non-blocking).
 * STANDARD_ERROR_MSG + LIQUID_ERROR_MSG = errors; optional STANDARD_WARNING_MSG = warnings.
 */
const groupByErrorsAndWarnings = (standardErrors, liquidErrors, standardWarnings = []) => {
  const errors = [];

  (standardErrors || []).forEach((message, index) => {
    errors.push({
      message,
      severity: SEVERITY.ERROR,
      index,
      source: 'standard',
    });
  });

  (liquidErrors || []).forEach((message, index) => {
    errors.push({
      message,
      severity: SEVERITY.ERROR,
      index,
      source: 'liquid',
    });
  });

  const warnings = (standardWarnings || []).map((message, index) => ({
    message,
    severity: SEVERITY.WARNING,
    index,
    source: 'standard',
  }));

  return { errors, warnings };
};

/**
 * Clean error message by removing line/char and rule parts
 * @param {string} message - Original error message
 * @param {RegExpMatchArray|null} lineMatch - Line number match result
 * @param {RegExpMatchArray|null} charMatch - Character number match result
 * @param {RegExpMatchArray|null} ruleMatch - Rule name match result
 * @returns {string} Cleaned message without line/char/rule information
 */
const cleanErrorMessage = (message, lineMatch, charMatch, ruleMatch) => {
  let displayMessage = message;
  if (lineMatch) {
    displayMessage = displayMessage.replace(/Line\s+\d+,?\s*/gi, '');
  }
  if (charMatch) {
    displayMessage = displayMessage.replace(/Char\s+\d+\.?\s*/gi, '');
  }
  if (ruleMatch) {
    displayMessage = displayMessage.replace(/•\s*[a-z-]+$/i, '');
  }
  return displayMessage.trim();
};

/**
 * Tab content component
 */
const TabContent = ({ issues, onErrorClick, intl }) => {
  if (!issues || issues.length === 0) {
    return null;
  }

  const handleNavigateClick = (issue, e) => {
    e.stopPropagation();
    if (onErrorClick) {
      onErrorClick(issue);
    }
  };

  return (
    <CapRow className="error-info-note__content">
      {issues.map((issue, index) => {
        const { severity, message } = issue;
        const key = `${message}-${index}`;

        // Parse line and char from message if present (format: "... Line X, Char Y.")
        const lineMatch = message.match(/Line\s+(\d+)/i);
        const charMatch = message.match(/Char\s+(\d+)/i);
        const line = lineMatch ? parseInt(lineMatch[1], 10) : null;
        const char = charMatch ? parseInt(charMatch[1], 10) : null;

        // Extract rule from message (format: "... • rule-name")
        const ruleMatch = message.match(/•\s*([a-z-]+)$/i);
        const rule = ruleMatch ? ruleMatch[1] : null;

        // Clean message (remove line/char and rule parts for display)
        const displayMessage = cleanErrorMessage(message, lineMatch, charMatch, ruleMatch);

        return (
          <CapRow
            key={key}
            className={`error-info-note__item error-info-note__item--${severity || 'error'}`}
          >
            <CapRow className="error-info-note__item-content">
              <CapLabelInline type="label2" className="error-info-note__item-message">
                {displayMessage}
              </CapLabelInline>
              {line && (
                <CapLabelInline type="label2" className="error-info-note__item-location">
                  <FormattedMessage {...messages.line} />
                  {' '}
                  {line}
                  {char ? (
                    <>
                      ,
                      {' '}
                      <FormattedMessage {...messages.char} />
                      {' '}
                      {char}
                    </>
                  ) : ''}
                  .
                </CapLabelInline>
              )}
              {rule && (
                <CapLabelInline type="label2" className="error-info-note__item-rule">
                  •
                  {' '}
                  {rule}
                </CapLabelInline>
              )}
            </CapRow>
            {onErrorClick && (
              <CapTooltip title={intl?.formatMessage ? intl.formatMessage(messages.navigateToError) : 'Go to error location'}>
                <CapButton
                  type="flat"
                  className="error-info-note__item-navigate"
                  onClick={(e) => handleNavigateClick({ ...issue, line, column: char }, e)}
                  aria-label={intl?.formatMessage ? intl.formatMessage(messages.navigateToError) : 'Go to error location'}
                >
                  <CapIcon type="redirection" />
                </CapButton>
              </CapTooltip>
            )}
          </CapRow>
        );
      })}
    </CapRow>
  );
};

TabContent.propTypes = {
  issues: PropTypes.array,
  onErrorClick: PropTypes.func,
  intl: PropTypes.object,
};

TabContent.defaultProps = {
  issues: [],
  onErrorClick: null,
  intl: null,
};

/**
 * ErrorInfoNote Component with Tabbed Interface
 * @param {boolean} useLegacyDisplay - If true, uses simple list display instead of tabbed interface (for BEE Editor)
 */
export const ErrorInfoNote = (props) => {
  const {
    errorMessages,
    onErrorClick,
    onClose,
    intl,
    useLegacyDisplay = false, // Use simple list display instead of tabs (for BEE Editor)
  } = props;

  const [isDismissed, setIsDismissed] = useState(false);
  const [activeKey, setActiveKey] = useState(null);

  const {
    LIQUID_ERROR_MSG: rawLiquidErrors = [],
    STANDARD_ERROR_MSG: rawStandardErrors = [],
    STANDARD_WARNING_MSG: rawStandardWarnings = [],
  } = errorMessages || {};

  // Detect if platform-specific (ANDROID/IOS) or GENERIC
  const isObject = typeof rawStandardErrors === 'object' && rawStandardErrors !== null;
  const isNotArray = !Array.isArray(rawLiquidErrors);
  const hasPlatformKeys = isObject && isNotArray && [ANDROID, IOS, GENERIC].some((key) => key in rawLiquidErrors);

  // Hooks must execute on every render before any conditional return.
  // Group into Errors (blocking) and Warnings (non-blocking)
  const { errors: errorIssues, warnings: warningIssues } = useMemo(() => groupByErrorsAndWarnings(
    Array.isArray(rawStandardErrors) ? rawStandardErrors : [],
    Array.isArray(rawLiquidErrors) ? rawLiquidErrors : [],
    Array.isArray(rawStandardWarnings) ? rawStandardWarnings : [],
  ), [rawStandardErrors, rawLiquidErrors, rawStandardWarnings]);

  const errorsCount = errorIssues?.length;
  const warningsCount = warningIssues?.length;
  const totalCount = errorsCount + warningsCount;
  const hasLiquidErrors = Array.isArray(rawLiquidErrors) && rawLiquidErrors.length > 0;

  // Default active tab: errors if any, else warnings
  useEffect(() => {
    if (errorsCount > 0) {
      setActiveKey(ERROR_TAB_KEYS.ERRORS);
    } else if (warningsCount > 0) {
      setActiveKey(ERROR_TAB_KEYS.WARNINGS);
    }
  }, [errorsCount, warningsCount]);

  // For platform-specific errors or when useLegacyDisplay is true, use the legacy renderer
  if (hasPlatformKeys) {
    // Process errors for both platforms - they use the same structure but different platform parameters
    const createPlatformErrors = (platform) => ({
      STANDARD: processErrors(rawStandardErrors, 'standard', platform, messages),
      LIQUID: processErrors(rawLiquidErrors, 'liquid', platform, messages),
    });

    const androidErrors = createPlatformErrors(ANDROID);
    const iosErrors = createPlatformErrors(IOS);
    return (
      <ErrorTypeRenderer
        genericErrors={null}
        androidErrors={androidErrors}
        iosErrors={iosErrors}
        ErrorSectionComponent={ErrorSection}
      />
    );
  }

  // For BEE Editor (useLegacyDisplay=true), use simple list display without tabs
  if (useLegacyDisplay) {
    const standardErrors = Array.isArray(rawStandardErrors) ? rawStandardErrors : [];
    const liquidErrors = Array.isArray(rawLiquidErrors) ? rawLiquidErrors : [];
    const hasStandardErrors = standardErrors.length > 0;
    const hasLiquidErrors = liquidErrors.length > 0;

    if (!hasStandardErrors && !hasLiquidErrors) {
      return null;
    }

    return (
      <CapRow className="error-container error-container--legacy">
        {hasStandardErrors && (
          <ErrorSection
            title={<FormattedMessage {...messages.standardErrorHeader} />}
            errors={standardErrors}
            liquidError={false}
          />
        )}
        {hasLiquidErrors && (
          <ErrorSection
            title={<FormattedMessage {...messages.dynamicErrorHeader} />}
            errors={liquidErrors}
            liquidError
          />
        )}
      </CapRow>
    );
  }

  // Handle close
  const handleClose = () => {
    setIsDismissed(true);
    if (onClose) {
      onClose();
    }
  };

  // Handle liquid documentation click
  const handleLiquidDocClick = () => {
    window.open(
      LIQUID_DOC_URL,
      '_blank',
    );
  };

  // Don't render if no issues or dismissed
  if (totalCount === 0 || isDismissed) {
    return null;
  }

  // Build tab panes: only Errors and Warnings
  const tabPanes = [];

  if (errorsCount > 0) {
    tabPanes.push({
      key: ERROR_TAB_KEYS.ERRORS,
      tab: (
        <CapLabelInline type="label2" className="error-info-note__tab-label error-info-note__tab-label--errors">
          <FormattedMessage {...messages.errors} />
          <CapLabelInline type="label2" className="error-info-note__tab-count">
            (
            {errorsCount}
            )
          </CapLabelInline>
        </CapLabelInline>
      ),
      content: (
        <TabContent
          issues={errorIssues}
          onErrorClick={onErrorClick}
          intl={intl}
        />
      ),
    });
  }

  if (warningsCount > 0) {
    tabPanes.push({
      key: ERROR_TAB_KEYS.WARNINGS,
      tab: (
        <CapLabelInline type="label2" className="error-info-note__tab-label error-info-note__tab-label--warnings">
          <FormattedMessage {...messages.warnings} />
          <CapLabelInline type="label2" className="error-info-note__tab-count">
            (
            {warningsCount}
            )
          </CapLabelInline>
        </CapLabelInline>
      ),
      content: (
        <TabContent
          issues={warningIssues}
          onErrorClick={onErrorClick}
          intl={intl}
        />
      ),
    });
  }

  return (
    <CapRow className="error-container error-container--tabs">
      <CapRow className="error-info-note__header">
        <CapTab
          activeKey={activeKey || (tabPanes[0]?.key)}
          onChange={setActiveKey}
          panes={tabPanes}
          className="error-info-note__tabs"
        />
        <CapRow className="error-info-note__actions">
          {hasLiquidErrors && (
            <CapButton
              type="flat"
              className="error-info-note__liquid-doc"
              onClick={handleLiquidDocClick}
            >
              <FormattedMessage {...messages.liquidDoc} />
              <CapIcon size="s" type="launch" />
            </CapButton>
          )}
          <CapTooltip title={intl?.formatMessage ? intl.formatMessage(messages.closePanel) : 'Close validation panel'}>
            <CapButton
              type="flat"
              className="error-info-note__close"
              onClick={handleClose}
              aria-label={intl?.formatMessage ? intl.formatMessage(messages.closePanel) : 'Close validation panel'}
            >
              <CapIcon type="close" />
            </CapButton>
          </CapTooltip>
        </CapRow>
      </CapRow>
    </CapRow>
  );
};

// Legacy ErrorSection component for platform-specific errors (backwards compatibility)
const ErrorSection = ({
  title,
  errors,
  liquidError,
  platformLabel,
}) => (
  <>
    {title && (
      <CapRow
        className={`error-header ${
          !liquidError ? 'standard-error-header' : ''
        }`}
      >
        <>
          <CapIcon size="s" type="warning" className="warning-icon" />
          {title}
        </>
        <>
          {liquidError && (
            <CapButton
              type="flat"
              className="add-btn"
              onClick={() => window.open(LIQUID_DOC_URL, '_blank')}
            >
              <FormattedMessage {...messages.liquidDoc} />
              <CapIcon size="s" type="launch" />
            </CapButton>
          )}
        </>
      </CapRow>
    )}
    {platformLabel && (
      <CapRow className="error-header-sub-title">
        <CapLabel type="label2">{platformLabel}</CapLabel>
      </CapRow>
    )}
    <CapRow className="error-list-legacy">
      {(errors || []).map((error) => (
        <CapRow key={`${error}`} className="error-list-legacy__item">
          <CapLabel type="label2" className="cap-list-v2-error-item">
            <CapLabel type="label2">{error}</CapLabel>
          </CapLabel>
        </CapRow>
      ))}
    </CapRow>
  </>
);

ErrorSection.propTypes = {
  title: PropTypes.node.isRequired,
  errors: PropTypes.array,
  liquidError: PropTypes.bool,
  platformLabel: PropTypes.string,
};

ErrorSection.defaultProps = {
  errors: [],
  liquidError: false,
  platformLabel: null,
};

ErrorInfoNote.defaultProps = {
  errorMessages: {
    LIQUID_ERROR_MSG: [],
    STANDARD_ERROR_MSG: [],
  },
  onErrorClick: null,
  onClose: null,
  intl: null,
  useLegacyDisplay: false, // Use simple list display for BEE Editor
};

ErrorInfoNote.propTypes = {
  errorMessages: PropTypes.shape({
    LIQUID_ERROR_MSG: PropTypes.oneOfType([
      PropTypes.array,
      PropTypes.shape({
        ANDROID: PropTypes.array,
        IOS: PropTypes.array,
        GENERIC: PropTypes.array,
      }),
    ]),
    STANDARD_ERROR_MSG: PropTypes.oneOfType([
      PropTypes.array,
      PropTypes.shape({
        ANDROID: PropTypes.array,
        IOS: PropTypes.array,
        GENERIC: PropTypes.array,
      }),
    ]),
    STANDARD_WARNING_MSG: PropTypes.array,
  }),
  onErrorClick: PropTypes.func,
  onClose: PropTypes.func,
  intl: PropTypes.object,
  useLegacyDisplay: PropTypes.bool, // Use simple list display for BEE Editor
};

export default injectIntl(ErrorInfoNote);
