import { useEffect, useState } from 'react';
import Taro from '@tarojs/taro';
import { Button, Text, View, WebView } from '@tarojs/components';
import {
  loadContentAssets,
  signAssetDownload,
  signAssetPreview,
  type AssetWatermarkContext,
  type ContentAsset,
  type SignedAssetLink,
} from '@/services/catalog';
import '../student.css';

type PreviewState = {
  kind: 'preview' | 'download';
  asset: ContentAsset;
  link: SignedAssetLink;
  watermark?: AssetWatermarkContext;
};

function openUrl(url?: string, copiedText = '签名链接已复制，请在浏览器中打开') {
  if (!url) return;
  if (process.env.TARO_ENV === 'h5' && typeof window !== 'undefined') {
    window.open(url, '_blank', 'noopener,noreferrer');
    return;
  }
  Taro.setClipboardData({ data: url });
  Taro.showToast({ title: copiedText, icon: 'none' });
}

function isImageAsset(asset: ContentAsset) {
  const mime = asset.mimeType || '';
  const type = asset.assetType || '';
  const name = asset.fileName || '';
  return mime.startsWith('image/') || type === 'image' || /\.(png|jpe?g|webp|gif)$/i.test(name);
}

function formatExpires(link?: SignedAssetLink) {
  if (link?.expiresAt) return `有效期至 ${new Date(link.expiresAt).toLocaleString()}`;
  if (link?.expiresInSec) return `约 ${link.expiresInSec} 秒后过期`;
  return '短期签名，离开页面后请重新申请';
}

function watermarkStyle(watermark?: AssetWatermarkContext) {
  return {
    opacity: String(watermark?.opacity ?? 0.16),
  };
}

function canOpenOutside(state: PreviewState | null) {
  if (!state?.link.url) return false;
  if (state.kind === 'download') return true;
  return state.watermark?.required !== true;
}

export default function StudentAssetsPage() {
  const [assets, setAssets] = useState<ContentAsset[]>([]);
  const [previewState, setPreviewState] = useState<PreviewState | null>(null);
  const [loadingAssetId, setLoadingAssetId] = useState('');
  const [error, setError] = useState('');

  useEffect(() => {
    loadContentAssets({ includeLocked: true })
      .then(payload => setAssets(payload.items || []))
      .catch(nextError => setError(nextError instanceof Error ? nextError.message : '资料加载失败'));
  }, []);

  async function preview(asset: ContentAsset) {
    try {
      setLoadingAssetId(asset.id);
      setError('');
      const payload = await signAssetPreview(asset.id);
      if (!payload.preview?.url) throw new Error('后端未返回可预览签名');
      setPreviewState({ kind: 'preview', asset: payload.item || asset, link: payload.preview, watermark: payload.watermark });
    } catch (nextError) {
      setError(nextError instanceof Error ? nextError.message : '预览失败');
    } finally {
      setLoadingAssetId('');
    }
  }

  async function download(asset: ContentAsset) {
    try {
      setLoadingAssetId(asset.id);
      setError('');
      const payload = await signAssetDownload(asset.id);
      if (!payload.download?.url) throw new Error('后端未返回可下载签名');
      const watermark = payload.watermark;
      if (watermark?.required) {
        setPreviewState({ kind: 'download', asset: payload.item || asset, link: payload.download, watermark });
        Taro.showToast({ title: '请确认水印追踪码后下载', icon: 'none' });
        return;
      }
      openUrl(payload.download?.url, '下载签名已复制，请及时使用');
    } catch (nextError) {
      setError(nextError instanceof Error ? nextError.message : '下载失败');
    } finally {
      setLoadingAssetId('');
    }
  }

  function openSignedLink() {
    openUrl(previewState?.link.url, previewState?.kind === 'download' ? '下载签名已复制，请及时使用' : '预览签名已复制，请及时打开');
  }

  return (
    <View className='student-page assets-page'>
      <View className='student-topbar'>
        <View className='student-title-block'>
          <Text className='student-kicker'>Assets</Text>
          <Text className='student-title'>资料下载</Text>
          <Text className='student-subtitle'>私有文件必须向后端申请短期签名，前端不直接拼对象存储地址。</Text>
        </View>
      </View>

      {previewState ? (
        <View className='asset-preview-panel section-block'>
          <View className='amount-row'>
            <View>
              <Text className='section-heading'>{previewState.kind === 'download' ? '确认下载' : '资料预览'} · {previewState.asset.title || previewState.asset.fileName || '未命名资料'}</Text>
              <Text className='row-meta'>{formatExpires(previewState.link)} · {previewState.link.signatureMode || 'signed'}</Text>
            </View>
            <Button className='secondary-button' onClick={() => setPreviewState(null)}>关闭</Button>
          </View>
          <View className='asset-preview-frame'>
            {previewState.kind === 'download' ? (
              <View className='asset-download-confirm'>
                <Text className='row-main'>已获取一次性下载授权</Text>
                <Text className='row-meta'>下载前请确认页面水印和追踪码。签名 URL 不会长期保存，过期后需要重新申请。</Text>
              </View>
            ) : null}
            {previewState.kind === 'preview' && process.env.TARO_ENV === 'h5' ? (
              <WebView className='asset-preview-iframe' src={previewState.link.url || ''} />
            ) : null}
            {previewState.kind === 'preview' && process.env.TARO_ENV !== 'h5' ? (
              <View className='asset-download-confirm'>
                <Text className='row-main'>已获取预览授权</Text>
                <Text className='row-meta'>当前小程序容器不直接嵌入私有文件。请先确认水印追踪码，再使用外部打开或复制签名链接。</Text>
              </View>
            ) : null}
            {previewState.watermark?.mode === 'visible_overlay' && previewState.watermark.required ? (
              <View className={`asset-watermark ${previewState.watermark.repeat ? 'repeat' : ''} ${previewState.watermark.position || 'diagonal'}`} style={watermarkStyle(previewState.watermark)}>
                <Text className='asset-watermark-text'>{previewState.watermark.text || previewState.watermark.traceId}</Text>
              </View>
            ) : null}
          </View>
          <View className='asset-security-strip'>
            <Text className='row-meta'>追踪码：{previewState.watermark?.traceId || '无'}。截图、转发或录屏外泄时，租户后台可按追踪码回查访问事件。</Text>
            <View className='toolbar wrap checkout-actions'>
              {isImageAsset(previewState.asset) && previewState.watermark?.required !== true ? (
                <Button className='secondary-button' onClick={() => Taro.previewImage({ current: previewState.link.url || '', urls: [previewState.link.url || ''] })}>系统看图</Button>
              ) : null}
              {canOpenOutside(previewState) ? (
                <Button className={previewState.kind === 'download' ? 'primary-button' : 'secondary-button'} onClick={openSignedLink}>{previewState.kind === 'download' ? '确认下载' : '外部打开'}</Button>
              ) : null}
            </View>
            {previewState.kind === 'preview' && previewState.watermark?.required ? (
              <Text className='row-meta'>该资源要求可见水印，不能脱离当前水印容器外部打开；小程序端如无法覆盖原生预览，请使用 H5 资料页查看。</Text>
            ) : null}
          </View>
        </View>
      ) : null}

      <View className='list-stack'>
        {assets.map(item => (
          <View className='list-row' key={item.id}>
            <Text className='row-main'>{item.title || item.fileName || '未命名资料'}</Text>
            <Text className='row-meta'>{item.assetType || 'asset'} · {item.visibility || 'public'}{item.previewStatus ? ` · ${item.previewStatus}` : ''}</Text>
            {item.description ? <Text className='row-meta'>{item.description}</Text> : null}
            <View className='toolbar'>
              <Button className='secondary-button' onClick={() => preview(item)}>{loadingAssetId === item.id ? '申请中' : '预览'}</Button>
              <Button className='primary-button' onClick={() => download(item)}>{loadingAssetId === item.id ? '申请中' : '下载'}</Button>
            </View>
          </View>
        ))}
      </View>
      {!assets.length ? <View className='empty-state'>暂无可见资料。</View> : null}
      {error ? <Text className='error-text'>{error}</Text> : null}
    </View>
  );
}
