import Taro from '@tarojs/taro';

import { Dialog } from '@taroify/core';
import { useCallback, useEffect, useState } from 'react';

import { DialogStatus, PREFIX } from '@/components/product-dialog/const';
import JobBuy from '@/components/product-dialog/steps-ui/job-buy';
import ContactCustomerService from '@/components/product-dialog/steps-ui/job-contact-customer';
import ContactDirect from '@/components/product-dialog/steps-ui/job-contact-direct';
import UnableUnlockContent from '@/components/product-dialog/steps-ui/job-unable';
import { DeclarationType, ProductType } from '@/constants/product';
import { JobDetails } from '@/types/job';
import { GetProductIsUnlockResponse, ProductInfo } from '@/types/product';
import { logWithPrefix } from '@/utils/common';
import { requestUseProduct } from '@/utils/product';
import Toast from '@/utils/toast';

import '../index.less';

interface IProps {
  data: JobDetails;
  /** Product use record from parent - if exists, user has already unlocked this job */
  productRecord?: GetProductIsUnlockResponse | null;
  /** Product balance info from parent */
  productInfo?: ProductInfo;
  /** Callback to refresh product balance in parent after purchase */
  onRefreshBalance?: () => Promise<ProductInfo | undefined>;
  onClose: () => void;
}

const PRODUCT_CODE = ProductType.VIP;
const log = logWithPrefix('product-job-contact-dialog');

/**
 * Integrated dialog component for job contact flow
 * Handles: balance check -> buy if needed -> use product -> show contact info
 *
 * @param productRecord - Pass from parent to avoid duplicate API calls
 * @param productInfo - Pass from parent to avoid duplicate API calls
 * @param onRefreshBalance - Callback to refresh balance in parent after purchase
 */
function ProductJobContactDialog(props: IProps) {
  const { data, productRecord, productInfo, onRefreshBalance, onClose } = props;
  const [status, setStatus] = useState<DialogStatus>(DialogStatus.LOADING);
  const [publisherAcctNo, setPublisherAcctNo] = useState<string>('');

  /**
   * Handle contact display based on declaration type
   */
  const showContactResult = useCallback((declarationTypeResult?: ProductInfo['declarationTypeResult']) => {
    if (declarationTypeResult?.type === DeclarationType.Direct && declarationTypeResult.publisherAcctNo) {
      log('show JOB_CONTACT_DIRECT', declarationTypeResult.publisherAcctNo);
      setPublisherAcctNo(declarationTypeResult.publisherAcctNo);
      setStatus(DialogStatus.JOB_CONTACT_DIRECT);
    } else {
      log('show JOB_CONTACT_CS');
      setStatus(DialogStatus.JOB_CONTACT_CS);
    }
  }, []);

  /**
   * Use product and show contact info
   */
  const consumeProductAndShowContact = useCallback(async () => {
    const productResult = await requestUseProduct(PRODUCT_CODE, { jobId: data.id });
    log('consumeProductAndShowContact result', productResult);
    // Refresh balance in parent after consuming product
    await onRefreshBalance?.();
    showContactResult(productResult?.declarationTypeResult);
  }, [data.id, showContactResult, onRefreshBalance]);

  /**
   * Callback after successful purchase
   * Refresh balance via parent callback and use product to show contact info
   */
  const handleAfterBuy = useCallback(async () => {
    log('handleAfterBuy - start');
    try {
      Taro.showLoading({ mask: true, title: '加载中...' });

      // Refresh balance via parent callback
      await onRefreshBalance?.();

      // Use product and show contact info after purchase
      await consumeProductAndShowContact();
    } catch (e) {
      log('handleAfterBuy error', e);
      Toast.error('出错了，请重试');
      onClose();
    } finally {
      Taro.hideLoading();
    }
  }, [consumeProductAndShowContact, onRefreshBalance, onClose]);

  const handleReport = useCallback(() => {
    log('report', data.id);
  }, [data.id]);

  /**
   * Initialize dialog on mount
   */
  useEffect(() => {
    let isMounted = true;

    const init = async () => {
      try {
        Taro.showLoading({ mask: true, title: '加载中...' });

        log('init with productRecord', productRecord);
        log('init with productInfo', productInfo);

        // Step 1: Already unlocked - show contact directly
        if (productRecord) {
          log('show JOB_CONTACT_DIRECT from productRecord', productRecord.declarationTypeResult);
          showContactResult(productRecord.declarationTypeResult);
          return;
        }

        // Step 2: No productInfo - error state
        if (!productInfo) {
          log('no productInfo provided, closing');
          Toast.error('出错了，请重试');
          onClose();
          return;
        }

        // Step 3: Determine status based on balance
        if (!productInfo.isPaidVip && !productInfo.freeBalance) {
          log('show JOB_BUY');
          if (isMounted) setStatus(DialogStatus.JOB_BUY);
        } else if (!productInfo.balance) {
          log('show JOB_UNABLE_UNLOCK');
          if (isMounted) setStatus(DialogStatus.JOB_UNABLE_UNLOCK);
        } else {
          await consumeProductAndShowContact();
        }
      } catch (e) {
        log('init error', e);
        Toast.error('出错了，请重试');
        onClose();
      } finally {
        Taro.hideLoading();
      }
    };

    init();

    return () => {
      isMounted = false;
    };
    // Only run on mount - props are captured at dialog open time
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, []);

  if (status === DialogStatus.LOADING) {
    return null;
  }

  return (
    <Dialog className={PREFIX} onClose={onClose} open>
      <Dialog.Content>
        {status === DialogStatus.JOB_CONTACT_CS && <ContactCustomerService onAfterConfirm={onClose} />}
        {status === DialogStatus.JOB_CONTACT_DIRECT && (
          <ContactDirect publisherAcctNo={publisherAcctNo} onAfterConfirm={onClose} onReport={handleReport} />
        )}
        {status === DialogStatus.JOB_BUY && (
          <JobBuy onConfirm={handleAfterBuy} isCreateResume={productInfo?.isCreateResume} />
        )}
        {status === DialogStatus.JOB_UNABLE_UNLOCK && <UnableUnlockContent onConfirm={onClose} />}
      </Dialog.Content>
    </Dialog>
  );
}

export default ProductJobContactDialog;
