import { useEffect, useRef, useState } from 'react';
import type { ActivityPosterItem, PartnerAssocSummary } from '@dukang/shared-types';
import { request } from '../lib/api';
import {
  copyActivityCopy,
  downloadBlob,
  fetchActivityPosterImage,
  fetchAssocQrcodeImage,
  getActivityPosterSelection,
  listActivityPosters,
  saveActivityPosterSelection,
} from '../lib/activity-posters';
import { toastError, toastSuccess } from '../lib/toast';
import { blobToDataUrl, isHttpImageUrl, previewSaveableImage } from '../lib/wechat-save-image';
import { isWechatEnv } from '../lib/weixin';

const NONE_ID = 'none';

type Props = {
  initialId?: string | null;
};

export default function ActivityPosterPicker({ initialId }: Props) {
  const [items, setItems] = useState<ActivityPosterItem[]>([]);
  const [qrcodeUrl, setQrcodeUrl] = useState<string | null>(null);
  const [partnerId, setPartnerId] = useState<string>('');
  const [selectedId, setSelectedId] = useState<string>(NONE_ID);
  const [previewUrls, setPreviewUrls] = useState<Record<string, string>>({});
  const [listLoading, setListLoading] = useState(true);
  const [previewLoading, setPreviewLoading] = useState(false);
  const [downloading, setDownloading] = useState(false);
  const blobsRef = useRef(new Map<string, Blob>());
  const urlsRef = useRef<string[]>([]);

  useEffect(() => () => {
    urlsRef.current.forEach((url) => URL.revokeObjectURL(url));
  }, []);

  useEffect(() => {
    let cancelled = false;
    Promise.all([
      listActivityPosters(),
      request<PartnerAssocSummary>('PARTNER_H5', '/partner/assoc', { silent: true }),
      getActivityPosterSelection().catch(() => ({ posterId: null })),
    ])
      .then(([list, assoc, selection]) => {
        if (cancelled) return;
        setItems(list);
        setQrcodeUrl(assoc.qrcodeUrl);
        setPartnerId(assoc.partnerId);
        const saved = selection.posterId && list.some((item) => item.id === selection.posterId)
          ? selection.posterId
          : null;
        const fromQuery = initialId && list.some((item) => item.id === initialId) ? initialId : null;
        const next = saved || fromQuery || NONE_ID;
        setSelectedId(next);
        if (!saved && fromQuery) {
          void saveActivityPosterSelection(fromQuery).catch((err) => {
            toastError(err instanceof Error ? err.message : '保存失败');
          });
        }
      })
      .catch((e) => toastError(e instanceof Error ? e.message : '加载活动图失败'))
      .finally(() => {
        if (!cancelled) setListLoading(false);
      });
    return () => {
      cancelled = true;
    };
  }, [initialId]);

  useEffect(() => {
    if (selectedId === NONE_ID || previewUrls[selectedId] || blobsRef.current.has(selectedId)) return;
    let cancelled = false;
    setPreviewLoading(true);
    fetchActivityPosterImage(selectedId)
      .then((blob) => {
        if (cancelled) return;
        blobsRef.current.set(selectedId, blob);
        const url = URL.createObjectURL(blob);
        urlsRef.current.push(url);
        setPreviewUrls((prev) => ({ ...prev, [selectedId]: url }));
      })
      .catch((e) => {
        if (!cancelled) toastError(e instanceof Error ? e.message : '预览失败');
      })
      .finally(() => {
        if (!cancelled) setPreviewLoading(false);
      });
    return () => {
      cancelled = true;
    };
  }, [selectedId, previewUrls]);

  const selected = items.find((item) => item.id === selectedId) ?? null;
  const previewUrl = selectedId !== NONE_ID ? previewUrls[selectedId] : undefined;

  async function downloadSelected() {
    setDownloading(true);
    try {
      if (selectedId === NONE_ID) {
        if (isWechatEnv() && isHttpImageUrl(qrcodeUrl)) {
          await previewSaveableImage(qrcodeUrl);
          return;
        }
        const blob = await fetchAssocQrcodeImage();
        if (isWechatEnv()) {
          setQrcodeUrl(await blobToDataUrl(blob));
          toastSuccess('请长按上方图片保存到相册');
          return;
        }
        downloadBlob(blob, `partner-assoc-${partnerId || 'qr'}.png`);
        toastSuccess('已开始下载');
        return;
      }
      if (!selected) return;
      let blob = blobsRef.current.get(selected.id);
      if (!blob) {
        blob = await fetchActivityPosterImage(selected.id);
        blobsRef.current.set(selected.id, blob);
      }
      if (isWechatEnv()) {
        let url = previewUrls[selected.id];
        if (!url || url.startsWith('blob:')) {
          url = await blobToDataUrl(blob);
          setPreviewUrls((prev) => ({ ...prev, [selected.id]: url }));
        }
        toastSuccess('请长按上方图片保存到相册');
        return;
      }
      downloadBlob(blob, `activity-poster-${selected.id}.png`);
      toastSuccess('已开始下载');
    } catch (e) {
      toastError(e instanceof Error ? e.message : '下载失败');
    } finally {
      setDownloading(false);
    }
  }

  async function selectPoster(id: string) {
    const prev = selectedId;
    setSelectedId(id);
    try {
      await saveActivityPosterSelection(id === NONE_ID ? null : id);
    } catch (e) {
      setSelectedId(prev);
      toastError(e instanceof Error ? e.message : '保存失败');
    }
  }

  function renderRadioRow(id: string, label: string) {
    return (
      <label className="partner-activity-radio-row">
        <span className="headline-md">{label}</span>
        <input
          type="radio"
          name="activity-poster"
          checked={selectedId === id}
          onChange={() => void selectPoster(id)}
        />
      </label>
    );
  }

  if (listLoading) {
    return <div className="empty">加载活动图…</div>;
  }

  return (
    <div className="partner-activity-picker">
      <section className="partner-bill-card" style={{ overflow: 'hidden' }}>
        {renderRadioRow(NONE_ID, '无')}
        {selectedId === NONE_ID && (
          <div className="partner-activity-panel">
            {qrcodeUrl ? (
              <div className="partner-activity-preview partner-activity-preview--qr">
                <img className="partner-longpress-img" src={qrcodeUrl} alt="关联码" />
              </div>
            ) : (
              <p className="body-md text-muted" style={{ marginBottom: 12 }}>关联码尚未生成</p>
            )}
            <button
              type="button"
              className="partner-btn-primary"
              disabled={downloading || !qrcodeUrl}
              onClick={() => void downloadSelected()}
            >
              {downloading ? '下载中…' : '下载二维码'}
            </button>
            {isWechatEnv() && (
              <p className="label-md text-muted" style={{ marginTop: 12 }}>
                微信内请长按上方图片保存
              </p>
            )}
          </div>
        )}
      </section>

      {items.map((item) => (
        <section key={item.id} className="partner-bill-card" style={{ marginTop: 12, overflow: 'hidden' }}>
          {renderRadioRow(item.id, item.title)}
          {selectedId === item.id && (
            <div className="partner-activity-panel">
              <div className="partner-activity-preview">
                <img className="partner-longpress-img" src={previewUrl || item.imageUrl} alt={item.title} />
                {previewLoading && !previewUrl && (
                  <div className="partner-activity-preview-mask">正在贴入二维码…</div>
                )}
              </div>
              {item.copyText ? (
                <p className="body-md" style={{ whiteSpace: 'pre-wrap', margin: '12px 0' }}>{item.copyText}</p>
              ) : (
                <p className="body-md text-muted" style={{ margin: '12px 0' }}>暂无推广文案</p>
              )}
              <div style={{ display: 'flex', gap: 12 }}>
                <button
                  type="button"
                  className="partner-btn-outline"
                  onClick={() => {
                    void copyActivityCopy(item.copyText)
                      .then(() => toastSuccess('文案已复制'))
                      .catch((e) => toastError(e instanceof Error ? e.message : '复制失败'));
                  }}
                >
                  复制文案
                </button>
                <button
                  type="button"
                  className="partner-btn-primary"
                  style={{ flex: 1, width: 'auto', padding: 0, height: 48 }}
                  disabled={downloading || previewLoading}
                  onClick={() => void downloadSelected()}
                >
                  {downloading || previewLoading ? '生成中…' : '下载活动图'}
                </button>
              </div>
              {previewUrl && isWechatEnv() && (
                <p className="label-md text-muted" style={{ marginTop: 12 }}>
                  微信内请长按上方图片保存
                </p>
              )}
            </div>
          )}
        </section>
      ))}
    </div>
  );
}
