import { useEffect, useId, useRef, useState } from 'react';
import { uploadFileToOss, type OssMediaType } from '../lib/upload';
import { toastError } from '../lib/toast';
import {
  authorizePartnerWechat,
  fetchClientConfig,
  fetchPartnerProfile,
  needsWechatAuth,
  type PartnerProfile,
} from '../lib/wechat-auth';
import { formatChooseImageFailMessage } from '@dukang/weixin-sdk';
import { isWechatEnv, weixinSdk } from '../lib/weixin';
import type { ClientRuntimeConfig } from '@dukang/shared-types';

type OssUploadFieldProps = {
  value?: string;
  onChange?: (url: string) => void;
  bizType: string;
  mediaType?: OssMediaType;
  accept?: string;
  wide?: boolean;
  compact?: boolean;
  label?: string;
  /** 父级已确认微信授权时可跳过检查 */
  wechatReady?: boolean;
  onWechatReadyChange?: (ready: boolean) => void;
};

const DEFAULT_MAX_MB = 10;

function formatWechatUploadError(e: unknown): string {
  const msg = e instanceof Error ? e.message : '无法打开相册';
  const formatted = formatChooseImageFailMessage(msg);
  if (formatted) return formatted;
  if (/invalid signature/i.test(msg)) {
    return '微信 JSSDK 签名校验失败：请确认公众号已配置 JS 接口安全域名为 user.runxian.top，并刷新页面后重试';
  }
  return msg;
}

export default function OssUploadField({
  value,
  onChange,
  bizType,
  mediaType = 'IMAGE',
  accept,
  wide,
  compact,
  label,
  wechatReady,
  onWechatReadyChange,
}: OssUploadFieldProps) {
  const inputId = useId();
  const inputRef = useRef<HTMLInputElement>(null);
  const [uploading, setUploading] = useState(false);
  const [authorizing, setAuthorizing] = useState(false);
  const [error, setError] = useState('');
  const [profile, setProfile] = useState<PartnerProfile | null>(null);
  const [clientConfig, setClientConfig] = useState<ClientRuntimeConfig | null>(null);

  const resolvedAccept =
    accept ?? (mediaType === 'VIDEO' ? 'video/*' : mediaType === 'FILE' ? 'image/*,.pdf' : 'image/*');
  const useWechatPicker = isWechatEnv() && mediaType === 'IMAGE';
  const needsAuth = useWechatPicker && needsWechatAuth(profile, clientConfig) && wechatReady !== true;

  useEffect(() => {
    if (!useWechatPicker) return;
    void Promise.all([fetchPartnerProfile(), fetchClientConfig()])
      .then(([me, config]) => {
        setProfile(me);
        setClientConfig(config);
        onWechatReadyChange?.(!!me.hasWechat);
      })
      .catch(() => {
        /* 未登录等场景由上传接口报错 */
      });
  }, [useWechatPicker, onWechatReadyChange]);

  useEffect(() => {
    if (!useWechatPicker || needsAuth) return;
    void weixinSdk.init().catch(() => {
      /* 点击上传时会再次初始化 */
    });
  }, [useWechatPicker, needsAuth]);

  async function uploadSelectedFile(file: File) {
    if (file.size > DEFAULT_MAX_MB * 1024 * 1024) {
      const text = `文件不能超过 ${DEFAULT_MAX_MB}MB`;
      setError(text);
      toastError(text);
      return;
    }
    setUploading(true);
    setError('');
    try {
      const result = await uploadFileToOss(file, { bizType, mediaType });
      onChange?.(result.url);
    } catch (e) {
      setError(e instanceof Error ? e.message : '上传失败');
    } finally {
      setUploading(false);
      if (inputRef.current) inputRef.current.value = '';
    }
  }

  async function startWechatAuth() {
    setAuthorizing(true);
    setError('');
    try {
      await authorizePartnerWechat();
    } catch (e) {
      const text = e instanceof Error ? e.message : '微信授权失败';
      setError(text);
      toastError(text);
      setAuthorizing(false);
    }
  }

  function openNativeFilePicker() {
    inputRef.current?.click();
  }

  async function pickWechatImage() {
    await weixinSdk.init();
    const files = await weixinSdk.chooseImages({
      count: 1,
      sourceType: ['album'],
    });
    if (files?.[0]) {
      await uploadSelectedFile(files[0]);
      return;
    }
    throw new Error('未能获取图片，请重试');
  }

  async function pickFile() {
    if (uploading || authorizing) return;
    setError('');

    if (useWechatPicker && needsAuth) {
      const text = '请先完成微信授权后再上传照片';
      setError(text);
      toastError(text);
      return;
    }

    if (useWechatPicker) {
      try {
        await pickWechatImage();
      } catch (e) {
        const msg = e instanceof Error ? e.message : '无法打开相册';
        if (/cancel/i.test(msg)) return;
        setError(formatWechatUploadError(e));
      }
      return;
    }

    openNativeFilePicker();
  }

  const isImage = mediaType === 'IMAGE' && value;
  const isFile = mediaType === 'FILE' && value;
  const busy = uploading || authorizing;

  const triggerProps = {
    type: 'button' as const,
    disabled: busy || needsAuth,
    onClick: () => void pickFile(),
  };

  return (
    <div className="partner-oss-upload">
      {needsAuth && (
        <div className="partner-wechat-auth-hint" role="status">
          <p className="body-md">上传照片需先完成微信授权</p>
          <button
            type="button"
            className="partner-btn-outline"
            style={{ marginTop: 8, width: '100%' }}
            disabled={authorizing}
            onClick={() => void startWechatAuth()}
          >
            {authorizing ? '跳转授权中…' : '微信授权'}
          </button>
        </div>
      )}
      <input
        id={inputId}
        ref={inputRef}
        type="file"
        accept={resolvedAccept}
        capture={mediaType === 'FILE' && isWechatEnv() ? 'environment' : undefined}
        className="partner-oss-upload-input"
        disabled={busy}
        onChange={(e) => {
          const file = e.target.files?.[0];
          if (file) void uploadSelectedFile(file);
        }}
      />
      {isImage ? (
        <button {...triggerProps} className={`partner-upload-preview${wide ? ' partner-upload-preview--wide' : ''}`}>
          <img src={value} alt={label ?? '已上传'} />
          <span className="partner-upload-preview-mask">
            <span className="material-symbols-outlined">{busy ? 'hourglass_top' : 'edit'}</span>
            <span>{uploading ? '上传中…' : '更换'}</span>
          </span>
        </button>
      ) : isFile ? (
        <button {...triggerProps} className="partner-upload-file">
          <div className="partner-bills-icon" style={{ background: '#ffb3ae' }}>
            <span className="material-symbols-outlined text-primary">description</span>
          </div>
          <div style={{ textAlign: 'left', flex: 1 }}>
            <span className="text-primary" style={{ fontWeight: 700, display: 'block' }}>已上传合同</span>
            <span className="label-md text-muted">{uploading ? '上传中…' : '点击更换'}</span>
          </div>
        </button>
      ) : (
        <button
          {...triggerProps}
          className={`partner-upload-dashed${wide ? ' partner-upload-dashed--wide' : ''}${compact ? ' partner-upload-dashed--compact' : ''}`}
        >
          <span className="material-symbols-outlined text-primary" style={{ fontSize: compact ? 28 : 36 }}>
            {busy ? 'hourglass_top' : 'add_a_photo'}
          </span>
          <span className="text-primary" style={{ fontWeight: 500 }}>
            {uploading ? '上传中…' : needsAuth ? '请先微信授权' : (label ?? (useWechatPicker ? '从相册选择' : '点击上传'))}
          </span>
        </button>
      )}
      {error && <p className="partner-form-error" role="alert">{error}</p>}
    </div>
  );
}
