'use client';

// ============================================================
// Presentation — App Version Management Page
// Clean Architecture: 纯表现层，只读 Redux/Zustand 状态，调用 Use Cases
// 不直接使用 HttpClient / apiClient / fetch
// ============================================================

import React, { useState } from 'react';
import { useQuery, useQueryClient } from '@tanstack/react-query';
import { t } from '@/i18n/locales';
import { useAppDispatch, useAppSelector } from '@/store';
import {
  setAppType, setPlatformFilter,
  openUploadModal, closeUploadModal,
  openEditModal, closeEditModal,
} from '@/store/slices/version.slice';
import { useUploadStore } from '@/store/zustand/upload.store';
import {
  listVersionsUseCase,
  parsePackageUseCase,
  uploadVersionUseCase,
  updateVersionUseCase,
  toggleVersionUseCase,
  deleteVersionUseCase,
} from '@/application/use-cases/version.use-cases';
import type { AppVersion, AppType, AppPlatform } from '@/domain/entities';
import type { UpdateVersionInput } from '@/domain/repositories/version.repository.interface';

/* ── Styles ── */

const loadingBox: React.CSSProperties = {
  display: 'flex', alignItems: 'center', justifyContent: 'center',
  padding: 40, color: 'var(--color-text-tertiary)',
};
const tabBtn = (active: boolean): React.CSSProperties => ({
  padding: '8px 20px', border: 'none',
  borderBottom: active ? '2px solid var(--color-primary)' : '2px solid transparent',
  background: 'transparent',
  color: active ? 'var(--color-primary)' : 'var(--color-text-secondary)',
  cursor: 'pointer', fontWeight: active ? 600 : 400,
});
const filterBtn = (active: boolean): React.CSSProperties => ({
  padding: '4px 14px',
  border: `1px solid ${active ? 'var(--color-primary)' : 'var(--color-border)'}`,
  borderRadius: 'var(--radius-full)',
  background: active ? 'var(--color-primary-surface)' : 'transparent',
  color: active ? 'var(--color-primary)' : 'var(--color-text-secondary)',
  cursor: 'pointer',
});
const primaryBtn: React.CSSProperties = {
  padding: '8px 20px', border: 'none', borderRadius: 'var(--radius-full)',
  background: 'var(--color-primary)', color: 'white', cursor: 'pointer',
};
const thStyle: React.CSSProperties = {
  padding: '12px 16px', textAlign: 'left', whiteSpace: 'nowrap',
  color: 'var(--color-text-tertiary)',
};
const tdStyle: React.CSSProperties = { padding: '12px 16px', color: 'var(--color-text-primary)' };
const badge = (bg: string, color: string): React.CSSProperties => ({
  padding: '2px 10px', borderRadius: 'var(--radius-full)', background: bg, color, fontWeight: 500,
});
const overlayStyle: React.CSSProperties = {
  position: 'fixed', inset: 0, background: 'rgba(0,0,0,0.4)',
  display: 'flex', alignItems: 'center', justifyContent: 'center', zIndex: 1000,
};
const modalStyle: React.CSSProperties = {
  background: 'var(--color-surface)', borderRadius: 'var(--radius-lg)',
  padding: 28, width: 520, maxHeight: '80vh', overflow: 'auto',
  boxShadow: 'var(--shadow-lg)',
};
const inputStyle: React.CSSProperties = {
  width: '100%', height: 40, border: '1px solid var(--color-border)',
  borderRadius: 'var(--radius-sm)', padding: '0 12px',
  background: 'var(--color-gray-50)', outline: 'none', boxSizing: 'border-box',
};
const labelStyle: React.CSSProperties = {
  display: 'block', marginBottom: 4, marginTop: 14,
  color: 'var(--color-text-secondary)',
};

/* ── Helpers ── */

function formatFileSize(bytes: string | number | null | undefined): string {
  const n = typeof bytes === 'string' ? parseInt(bytes, 10) : (bytes ?? 0);
  if (!n || isNaN(n)) return '-';
  if (n < 1024) return `${n} B`;
  if (n < 1024 * 1024) return `${(n / 1024).toFixed(1)} KB`;
  if (n < 1024 * 1024 * 1024) return `${(n / (1024 * 1024)).toFixed(1)} MB`;
  return `${(n / (1024 * 1024 * 1024)).toFixed(2)} GB`;
}

function formatDate(iso: string | null | undefined): string {
  if (!iso) return '-';
  return new Date(iso).toLocaleDateString('zh-CN', {
    year: 'numeric', month: '2-digit', day: '2-digit',
    hour: '2-digit', minute: '2-digit',
  });
}

/* ── Query key factory ── */
const versionKeys = {
  list: (appType: AppType, platform: AppPlatform | '') =>
    ['versions', appType, platform] as const,
};

/* ── Main Page ── */

export const AppVersionManagementPage: React.FC = () => {
  const dispatch = useAppDispatch();
  const { appType, platformFilter, showUpload, editingVersionId } =
    useAppSelector((s) => s.versions);
  const queryClient = useQueryClient();

  const { data: versions, isLoading, error } = useQuery({
    queryKey: versionKeys.list(appType, platformFilter),
    queryFn: () => listVersionsUseCase.execute(appType, platformFilter as AppPlatform | undefined),
    staleTime: 30_000,
  });

  const invalidate = () =>
    queryClient.invalidateQueries({ queryKey: ['versions', appType] });

  const handleToggle = async (v: AppVersion) => {
    await toggleVersionUseCase.execute(v.id, !v.isEnabled);
    invalidate();
  };

  const handleDelete = async (v: AppVersion) => {
    if (!confirm(t('app_version_confirm_delete'))) return;
    await deleteVersionUseCase.execute(v.id);
    invalidate();
  };

  const list = Array.isArray(versions) ? versions : [];
  const editingVersion = editingVersionId ? list.find((v) => v.id === editingVersionId) ?? null : null;

  return (
    <div>
      <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: 20 }}>
        <h1 style={{ margin: 0 }}>{t('app_version_title')}</h1>
        <button style={primaryBtn} onClick={() => dispatch(openUploadModal())}>
          + {t('app_version_upload')}
        </button>
      </div>

      {/* App type tabs — RTK state */}
      <div style={{ display: 'flex', borderBottom: '1px solid var(--color-border-light)', marginBottom: 16 }}>
        {(['GENEX_MOBILE', 'ADMIN_APP'] as AppType[]).map((at) => (
          <button key={at} style={tabBtn(appType === at)} onClick={() => dispatch(setAppType(at))}>
            {at === 'GENEX_MOBILE' ? t('app_version_genex_mobile') : t('app_version_admin_app')}
          </button>
        ))}
      </div>

      {/* Platform filter — RTK state */}
      <div style={{ display: 'flex', gap: 8, marginBottom: 20 }}>
        {(['', 'ANDROID', 'IOS'] as (AppPlatform | '')[]).map((p) => (
          <button key={p || 'all'} style={filterBtn(platformFilter === p)}
            onClick={() => dispatch(setPlatformFilter(p as AppPlatform | ''))}>
            {p === '' ? t('app_version_all_platforms') : p === 'ANDROID' ? 'Android' : 'iOS'}
          </button>
        ))}
      </div>

      {/* Table */}
      {error ? (
        <div style={loadingBox}>Error: {(error as Error).message}</div>
      ) : isLoading ? (
        <div style={loadingBox}>Loading...</div>
      ) : list.length === 0 ? (
        <div style={loadingBox}>{t('app_version_no_versions')}</div>
      ) : (
        <div style={{ background: 'var(--color-surface)', borderRadius: 'var(--radius-md)', border: '1px solid var(--color-border-light)', overflow: 'auto' }}>
          <table style={{ width: '100%', borderCollapse: 'collapse' }}>
            <thead>
              <tr style={{ background: 'var(--color-gray-50)', borderBottom: '1px solid var(--color-border)' }}>
                <th style={thStyle}>{t('app_version_version_name')}</th>
                <th style={thStyle}>{t('app_version_platform')}</th>
                <th style={thStyle}>{t('app_version_build_number')}</th>
                <th style={thStyle}>{t('app_version_file_size')}</th>
                <th style={thStyle}>{t('app_version_force_update')}</th>
                <th style={thStyle}>{t('status')}</th>
                <th style={thStyle}>{t('app_version_release_date')}</th>
                <th style={thStyle}>{t('actions')}</th>
              </tr>
            </thead>
            <tbody>
              {list.map((v) => (
                <tr key={v.id} style={{ borderBottom: '1px solid var(--color-border-light)' }}>
                  <td style={{ ...tdStyle, fontWeight: 600 }}>{v.versionName}</td>
                  <td style={tdStyle}>
                    <span style={badge(
                      v.platform === 'ANDROID' ? 'var(--color-success-light)' : 'var(--color-info-light)',
                      v.platform === 'ANDROID' ? 'var(--color-success)' : 'var(--color-info)',
                    )}>
                      {v.platform === 'ANDROID' ? 'Android' : 'iOS'}
                    </span>
                  </td>
                  <td style={tdStyle}>{v.buildNumber}</td>
                  <td style={tdStyle}>{formatFileSize(v.fileSize)}</td>
                  <td style={tdStyle}>
                    {v.isForceUpdate
                      ? <span style={badge('var(--color-error-light)', 'var(--color-error)')}>{t('app_version_force_update')}</span>
                      : '-'}
                  </td>
                  <td style={tdStyle}>
                    <span style={badge(
                      v.isEnabled ? 'var(--color-success-light)' : 'var(--color-gray-100)',
                      v.isEnabled ? 'var(--color-success)' : 'var(--color-text-tertiary)',
                    )}>
                      {v.isEnabled ? t('app_version_enabled') : t('app_version_disabled')}
                    </span>
                  </td>
                  <td style={tdStyle}>{formatDate(v.releaseDate || v.createdAt)}</td>
                  <td style={{ ...tdStyle, whiteSpace: 'nowrap' }}>
                    <button onClick={() => dispatch(openEditModal(v.id))}
                      style={{ border: '1px solid var(--color-border)', borderRadius: 'var(--radius-sm)', padding: '3px 10px', background: 'transparent', cursor: 'pointer', marginRight: 6 }}>
                      {t('edit')}
                    </button>
                    <button onClick={() => handleToggle(v)}
                      style={{ border: `1px solid ${v.isEnabled ? 'var(--color-warning)' : 'var(--color-success)'}`, borderRadius: 'var(--radius-sm)', padding: '3px 10px', background: 'transparent', cursor: 'pointer', color: v.isEnabled ? 'var(--color-warning)' : 'var(--color-success)', marginRight: 6 }}>
                      {v.isEnabled ? t('disable') : t('enable')}
                    </button>
                    <button onClick={() => handleDelete(v)}
                      style={{ border: '1px solid var(--color-error)', borderRadius: 'var(--radius-sm)', padding: '3px 10px', background: 'transparent', cursor: 'pointer', color: 'var(--color-error)' }}>
                      {t('delete')}
                    </button>
                  </td>
                </tr>
              ))}
            </tbody>
          </table>
        </div>
      )}

      {showUpload && (
        <UploadModal
          appType={appType}
          onClose={() => dispatch(closeUploadModal())}
          onSuccess={() => { dispatch(closeUploadModal()); invalidate(); }}
        />
      )}

      {editingVersion && (
        <EditModal
          version={editingVersion}
          onClose={() => dispatch(closeEditModal())}
          onSuccess={() => { dispatch(closeEditModal()); invalidate(); }}
        />
      )}
    </div>
  );
};

/* ── Upload Modal — reads/writes Zustand upload store ── */

const UploadModal: React.FC<{
  appType: AppType;
  onClose: () => void;
  onSuccess: () => void;
}> = ({ appType, onClose, onSuccess }) => {
  const {
    file, platform, versionName, buildNumber, changelog, minOsVersion, isForceUpdate,
    isParsing, parseWarning, isUploading, uploadError,
    setFile, setPlatform, setVersionName, setBuildNumber, setChangelog,
    setMinOsVersion, setIsForceUpdate, setIsParsing, setParseWarning,
    setIsUploading, setUploadError, reset,
  } = useUploadStore();

  const handleFileChange = async (e: React.ChangeEvent<HTMLInputElement>) => {
    const f = e.target.files?.[0];
    if (!f) return;
    setFile(f);
    setParseWarning('');
    if (f.name.endsWith('.apk')) setPlatform('ANDROID');
    else if (f.name.endsWith('.ipa')) setPlatform('IOS');

    setIsParsing(true);
    try {
      console.log('[Upload] Parsing:', f.name, (f.size / 1024 / 1024).toFixed(1) + 'MB');
      const info = await parsePackageUseCase.execute(f);
      console.log('[Upload] Parse result:', info);
      if (info?.versionName) setVersionName(info.versionName);
      if (info?.versionCode) setBuildNumber(String(info.versionCode));
      if (info?.minSdkVersion) setMinOsVersion(info.minSdkVersion);
    } catch (err: any) {
      console.warn('[Upload] Parse failed:', err?.message);
      setParseWarning('无法自动解析安装包信息，请手动填写版本号');
    }
    setIsParsing(false);
  };

  const handleSubmit = async () => {
    if (!file) { setUploadError(t('app_version_upload_file')); return; }
    setIsUploading(true);
    setUploadError('');
    try {
      console.log('[Upload] Uploading:', file.name, (file.size / 1024 / 1024).toFixed(1) + 'MB');
      const result = await uploadVersionUseCase.execute({
        file, appType, platform, versionName, buildNumber,
        changelog, minOsVersion, isForceUpdate,
      });
      console.log('[Upload] Success:', result);
      reset();
      onSuccess();
    } catch (err: any) {
      console.error('[Upload] Failed:', err);
      setUploadError(err?.message || 'Upload failed');
    }
    setIsUploading(false);
  };

  const handleClose = () => { reset(); onClose(); };

  return (
    <div style={overlayStyle} onClick={handleClose}>
      <div style={modalStyle} onClick={(e) => e.stopPropagation()}>
        <h2 style={{ margin: '0 0 8px' }}>{t('app_version_upload')}</h2>

        <label style={labelStyle}>{t('app_version_upload_file')}</label>
        <input type="file" accept=".apk,.ipa" onChange={handleFileChange}
          style={{ ...inputStyle, padding: '8px 12px', height: 'auto' }} />
        {file && (
          <div style={{ color: 'var(--color-text-secondary)', marginTop: 4 }}>
            {file.name} ({(file.size / 1024 / 1024).toFixed(1)} MB)
          </div>
        )}
        {isParsing && (
          <div style={{ color: 'var(--color-info)', marginTop: 4 }}>
            {t('app_version_parsing')}{file && file.size > 30 * 1024 * 1024 ? '（大文件，请耐心等待...）' : ''}
          </div>
        )}
        {parseWarning && (
          <div style={{ color: 'var(--color-warning, #f90)', marginTop: 4 }}>{parseWarning}</div>
        )}

        <label style={labelStyle}>{t('app_version_platform')}</label>
        <div style={{ display: 'flex', gap: 12 }}>
          {(['ANDROID', 'IOS'] as AppPlatform[]).map((p) => (
            <label key={p} style={{ cursor: 'pointer', display: 'flex', alignItems: 'center', gap: 4 }}>
              <input type="radio" checked={platform === p} onChange={() => setPlatform(p)} />
              {p === 'ANDROID' ? 'Android' : 'iOS'}
            </label>
          ))}
        </div>

        <label style={labelStyle}>
          {t('app_version_version_name')}
          <span style={{ color: 'var(--color-text-secondary)', fontWeight: 400, marginLeft: 6 }}>
            ({t('optional_auto_from_apk')})
          </span>
        </label>
        <input style={inputStyle} value={versionName} onChange={(e) => setVersionName(e.target.value)} placeholder="1.0.0" />

        <label style={labelStyle}>{t('app_version_build_number')}</label>
        <input style={inputStyle} value={buildNumber} onChange={(e) => setBuildNumber(e.target.value)} placeholder="100" />

        <label style={labelStyle}>{t('app_version_min_os')}</label>
        <input style={inputStyle} value={minOsVersion} onChange={(e) => setMinOsVersion(e.target.value)}
          placeholder={platform === 'ANDROID' ? 'e.g. 8.0' : 'e.g. 14.0'} />

        <label style={labelStyle}>{t('app_version_changelog')}</label>
        <textarea value={changelog} onChange={(e) => setChangelog(e.target.value)} rows={3}
          style={{ ...inputStyle, height: 'auto', padding: '8px 12px', resize: 'vertical' }} />

        <label style={{ ...labelStyle, display: 'flex', alignItems: 'center', gap: 8, marginTop: 16 }}>
          <input type="checkbox" checked={isForceUpdate} onChange={(e) => setIsForceUpdate(e.target.checked)} />
          {t('app_version_force_update')}
        </label>

        {uploadError && <div style={{ color: 'var(--color-error)', marginTop: 8 }}>{uploadError}</div>}
        {isUploading && <div style={{ color: 'var(--color-info)', marginTop: 4 }}>正在上传，大文件需要较长时间，请耐心等待...</div>}

        <div style={{ display: 'flex', gap: 12, marginTop: 20, justifyContent: 'flex-end' }}>
          <button onClick={handleClose}
            style={{ padding: '8px 20px', border: '1px solid var(--color-border)', borderRadius: 'var(--radius-full)', background: 'transparent', cursor: 'pointer' }}>
            {t('cancel')}
          </button>
          <button onClick={handleSubmit} disabled={isUploading || isParsing}
            style={{ ...primaryBtn, opacity: isUploading || isParsing ? 0.6 : 1 }}>
            {isUploading ? t('app_version_uploading') : t('confirm')}
          </button>
        </div>
      </div>
    </div>
  );
};

/* ── Edit Modal — local useState (无需持久化，单次操作) ── */

const EditModal: React.FC<{
  version: AppVersion;
  onClose: () => void;
  onSuccess: () => void;
}> = ({ version, onClose, onSuccess }) => {
  const [changelog, setChangelog] = useState(version.changelog);
  const [minOsVersion, setMinOsVersion] = useState(version.minOsVersion ?? '');
  const [isForceUpdate, setIsForceUpdate] = useState(version.isForceUpdate);
  const [isEnabled, setIsEnabled] = useState(version.isEnabled);
  const [saving, setSaving] = useState(false);
  const [error, setError] = useState('');

  const handleSave = async () => {
    setSaving(true);
    setError('');
    try {
      const input: UpdateVersionInput = {
        changelog,
        minOsVersion: minOsVersion || null,
        isForceUpdate,
        isEnabled,
      };
      await updateVersionUseCase.execute(version.id, input);
      onSuccess();
    } catch (err: any) {
      setError(err?.message || 'Save failed');
    }
    setSaving(false);
  };

  return (
    <div style={overlayStyle} onClick={onClose}>
      <div style={modalStyle} onClick={(e) => e.stopPropagation()}>
        <h2 style={{ margin: '0 0 4px' }}>{t('app_version_edit')}</h2>
        <div style={{ color: 'var(--color-text-tertiary)', marginBottom: 16 }}>
          {version.platform === 'ANDROID' ? 'Android' : 'iOS'} · v{version.versionName} · Build {version.buildNumber}
        </div>

        <label style={labelStyle}>{t('app_version_changelog')}</label>
        <textarea value={changelog} onChange={(e) => setChangelog(e.target.value)} rows={4}
          style={{ ...inputStyle, height: 'auto', padding: '8px 12px', resize: 'vertical' }} />

        <label style={labelStyle}>{t('app_version_min_os')}</label>
        <input style={inputStyle} value={minOsVersion} onChange={(e) => setMinOsVersion(e.target.value)}
          placeholder={version.platform === 'ANDROID' ? 'e.g. 8.0' : 'e.g. 14.0'} />

        <label style={{ ...labelStyle, display: 'flex', alignItems: 'center', gap: 8, marginTop: 16 }}>
          <input type="checkbox" checked={isForceUpdate} onChange={(e) => setIsForceUpdate(e.target.checked)} />
          {t('app_version_force_update')}
        </label>

        <label style={{ ...labelStyle, display: 'flex', alignItems: 'center', gap: 8 }}>
          <input type="checkbox" checked={isEnabled} onChange={(e) => setIsEnabled(e.target.checked)} />
          {t('app_version_enabled')}
        </label>

        {error && <div style={{ color: 'var(--color-error)', marginTop: 8 }}>{error}</div>}

        <div style={{ display: 'flex', gap: 12, marginTop: 20, justifyContent: 'flex-end' }}>
          <button onClick={onClose}
            style={{ padding: '8px 20px', border: '1px solid var(--color-border)', borderRadius: 'var(--radius-full)', background: 'transparent', cursor: 'pointer' }}>
            {t('cancel')}
          </button>
          <button onClick={handleSave} disabled={saving}
            style={{ ...primaryBtn, opacity: saving ? 0.6 : 1 }}>
            {saving ? '...' : t('save')}
          </button>
        </div>
      </div>
    </div>
  );
};
