import { useCallback, useEffect, useRef, useState } from 'react';
import { motion, AnimatePresence } from 'motion/react';
import {
  Upload, FileSpreadsheet, RotateCcw, CheckCircle2, AlertCircle,
  Truck, ExternalLink, Layers, Zap, ArrowLeft,
} from 'lucide-react';
import { fetchJson } from '../../auth/api-client';
import { useAuth } from '../../auth/useAuth';
import RotatingFooterHint from '../../components/RotatingFooterHint';
import FeedbackFab from '../../components/FeedbackFab';
import { PageFrame } from '../../components/ui/surface';

function getJwt(): string | null {
  return sessionStorage.getItem('bi_jwt');
}

interface UploadResult {
  ok: boolean;
  filename: string;
  batchId: string;
  parsed: number;
  fileDuplicates: number;
  inserted: number;
  dbDuplicates: number;
  breakdown: { internal: number; external: number };
}

interface ListItem {
  id: number;
  order_no: string;
  station_name: string | null;
  terminal_name: string | null;
  region: string | null;
  city: string | null;
  start_time: string | null;
  end_time: string | null;
  duration_min: number | null;
  kwh: number | null;
  fee: number | null;
  e_fee: number | null;
  service_fee: number | null;
  plate: string | null;
  judged_plate: string | null;
  customer_name: string | null;
  vehicle_kind: 'internal' | 'external' | 'unknown';
  batch_id: string;
  imported_at: string;
}

interface OverallRow { vehicle_kind: 'internal' | 'external'; records: number; total_kwh: number; total_fee: number; }
interface BatchRow { batch_id: string; imported_at: string; records: number; internal_count: number; external_count: number; total_kwh: number; total_fee: number; }

const KIND_LABEL: Record<string, string> = {
  internal: '内部',
  external: '外部',
};
const KIND_STYLE: Record<string, string> = {
  internal: 'bg-blue-50 text-blue-600 border-blue-200',
  external: 'bg-amber-50 text-amber-600 border-amber-200',
};

async function uploadFile(file: File): Promise<UploadResult> {
  const fd = new FormData();
  fd.append('file', file);
  const token = getJwt();
  const res = await fetch('/api/ele/import', {
    method: 'POST',
    headers: token ? { Authorization: `Bearer ${token}` } : {},
    body: fd,
  });
  const json = await res.json();
  if (!res.ok || !json.ok) throw new Error(json.message || `上传失败 (${res.status})`);
  return json as UploadResult;
}

export default function EleImportPage() {
  const { user } = useAuth();
  const [file, setFile] = useState<File | null>(null);
  const [uploading, setUploading] = useState(false);
  const [result, setResult] = useState<UploadResult | null>(null);
  const [error, setError] = useState<string | null>(null);
  const [items, setItems] = useState<ListItem[]>([]);
  const [total, setTotal] = useState(0);
  const [overall, setOverall] = useState<OverallRow[]>([]);
  const [batches, setBatches] = useState<BatchRow[]>([]);
  const [filter, setFilter] = useState<'' | 'internal' | 'external'>('');
  const [batchFilter, setBatchFilter] = useState('');
  const [search, setSearch] = useState('');
  const [searchInput, setSearchInput] = useState('');
  const [dragOver, setDragOver] = useState(false);
  const inputRef = useRef<HTMLInputElement>(null);

  const reload = useCallback(async () => {
    const params = new URLSearchParams({ page: '1', limit: '50' });
    if (filter) params.set('kind', filter);
    if (batchFilter) params.set('batchId', batchFilter);
    if (search) params.set('search', search);
    const [list, agg, b] = await Promise.all([
      fetchJson<{ items: ListItem[]; total: number }>(`/api/ele/list?${params.toString()}`),
      fetchJson<{ overall: OverallRow[] }>(`/api/ele/aggregate`),
      fetchJson<{ items: BatchRow[] }>(`/api/ele/batches`),
    ]);
    setItems(list.items);
    setTotal(list.total);
    setOverall(agg.overall);
    setBatches(b.items);
  }, [filter, batchFilter, search]);

  useEffect(() => {
    reload().catch(e => console.error(e));
  }, [reload]);

  const handleUpload = async (f: File) => {
    setUploading(true);
    setError(null);
    setResult(null);
    try {
      const r = await uploadFile(f);
      setResult(r);
      await reload();
    } catch (e) {
      setError(e instanceof Error ? e.message : String(e));
    } finally {
      setUploading(false);
    }
  };

  const onPick = (f: File | null) => {
    setFile(f);
    if (f) handleUpload(f);
  };

  const overallMap = new Map(overall.map(o => [o.vehicle_kind, o]));
  const totalRecords = overall.reduce((s, o) => s + Number(o.records || 0), 0);
  const totalKwh = overall.reduce((s, o) => s + Number(o.total_kwh || 0), 0);
  const totalFee = overall.reduce((s, o) => s + Number(o.total_fee || 0), 0);

  return (
    <PageFrame
      title="充电记录导入"
      subtitle="每日上传 xlsx，按订单编号去重，并自动匹配内部/外部车辆归属。"
      icon={Zap}
      eyebrow="ELECTRIC IMPORT"
      meta={user?.userName || '导入工作台'}
      actions={(
        <div className="flex items-center gap-2">
            <button
              onClick={() => {
                if (window.history.length > 1) window.history.back();
                else { window.location.hash = '#mileage'; }
              }}
              className="flex h-9 w-9 items-center justify-center rounded-xl border border-slate-100 bg-white text-slate-500 transition-colors hover:border-blue-200 hover:bg-blue-50 hover:text-blue-600"
              title="返回"
            >
              <ArrowLeft size={16} />
            </button>
          <button
            onClick={() => inputRef.current?.click()}
            className="inline-flex h-9 items-center gap-1.5 rounded-xl bg-slate-900 px-3 text-xs font-black text-white shadow-sm transition-colors hover:bg-slate-800"
          >
            <Upload size={14} />
            上传文件
          </button>
        </div>
      )}
    >

        {/* 上传区 */}
        <section
          onDragOver={(e) => { e.preventDefault(); setDragOver(true); }}
          onDragLeave={() => setDragOver(false)}
          onDrop={(e) => {
            e.preventDefault();
            setDragOver(false);
            const f = e.dataTransfer.files?.[0];
            if (f) onPick(f);
          }}
          onClick={() => inputRef.current?.click()}
          className={`bg-white rounded-2xl border-2 border-dashed shadow-sm cursor-pointer transition-all ${
            dragOver ? 'border-blue-400 bg-blue-50/40' : uploading ? 'border-slate-200' : 'border-slate-200 hover:border-blue-300'
          }`}
        >
          <input
            ref={inputRef}
            type="file"
            accept=".xlsx,.xls"
            className="hidden"
            onChange={(e) => onPick(e.target.files?.[0] || null)}
          />
          <div className="px-6 py-10 flex flex-col items-center text-center">
            <div className="w-14 h-14 rounded-2xl bg-blue-50 flex items-center justify-center mb-3">
              {uploading ? <RotateCcw size={22} className="text-blue-500 animate-spin" /> : <Upload size={22} className="text-blue-500" />}
            </div>
            <div className="text-sm font-bold text-slate-700 mb-1">
              {uploading ? '正在解析...' : file ? file.name : '点击或拖拽 xlsx 文件到此处'}
            </div>
            <div className="text-[11px] text-slate-400 max-w-md leading-relaxed">
              支持「充电成功记录明细」格式；订单编号已存在的会自动跳过
            </div>
          </div>
        </section>

        {/* 上传结果提示 */}
        <AnimatePresence>
          {result && (
            <motion.div
              initial={{ opacity: 0, y: 8 }}
              animate={{ opacity: 1, y: 0 }}
              exit={{ opacity: 0, y: -8 }}
              className="bg-white rounded-2xl border border-emerald-100 shadow-sm p-4 flex items-start gap-3"
            >
              <CheckCircle2 size={18} className="text-emerald-500 flex-shrink-0 mt-0.5" />
              <div className="flex-1 min-w-0">
                <div className="text-[12px] font-bold text-slate-700 mb-1">
                  上传成功：<span className="text-slate-500 font-mono">{result.filename}</span>
                </div>
                <div className="grid grid-cols-2 md:grid-cols-5 gap-2 text-[11px]">
                  <Stat label="解析" value={result.parsed} color="text-slate-700" />
                  <Stat label="新增" value={result.inserted} color="text-blue-600" />
                  <Stat label="重复跳过" value={result.fileDuplicates + result.dbDuplicates} color="text-slate-500" />
                  <Stat label="内部" value={result.breakdown.internal} color="text-blue-600" />
                  <Stat label="外部（含无车牌）" value={result.breakdown.external} color="text-amber-600" />
                </div>
              </div>
              <button onClick={() => setResult(null)} className="text-slate-300 hover:text-slate-600 text-[10px] font-bold">关闭</button>
            </motion.div>
          )}
        </AnimatePresence>
        <AnimatePresence>
          {error && (
            <motion.div
              initial={{ opacity: 0, y: 8 }}
              animate={{ opacity: 1, y: 0 }}
              exit={{ opacity: 0, y: -8 }}
              className="bg-red-50 rounded-2xl border border-red-200 shadow-sm p-4 flex items-start gap-3"
            >
              <AlertCircle size={18} className="text-red-500 flex-shrink-0 mt-0.5" />
              <div className="flex-1 text-[12px] font-bold text-red-700">{error}</div>
              <button onClick={() => setError(null)} className="text-red-300 hover:text-red-600 text-[10px] font-bold">关闭</button>
            </motion.div>
          )}
        </AnimatePresence>

        {/* 聚合卡 */}
        <section className="grid grid-cols-2 md:grid-cols-3 gap-2">
          <KpiCard icon={<Layers size={14} />} label="总记录" value={totalRecords.toLocaleString()} />
          <KpiCard icon={<Truck size={14} />} label="内部记录" value={(overallMap.get('internal')?.records ?? 0).toLocaleString()} accent="blue" />
          <KpiCard icon={<ExternalLink size={14} />} label="外部记录" value={(overallMap.get('external')?.records ?? 0).toLocaleString()} accent="amber" />
          <KpiCard icon={<Zap size={14} />} label="累计电量" value={`${totalKwh.toLocaleString('zh-CN', { maximumFractionDigits: 1 })} 度`} />
          <KpiCard icon={<Zap size={14} />} label="内部电量" value={`${(overallMap.get('internal')?.total_kwh ?? 0).toLocaleString('zh-CN', { maximumFractionDigits: 1 })} 度`} accent="blue" />
          <KpiCard icon={<Zap size={14} />} label="外部电量" value={`${(overallMap.get('external')?.total_kwh ?? 0).toLocaleString('zh-CN', { maximumFractionDigits: 1 })} 度`} accent="amber" />
        </section>

        {/* 批次 */}
        {batches.length > 0 && (
          <section className="bg-white rounded-2xl border border-slate-100 shadow-sm overflow-hidden">
            <div className="px-3 py-2 bg-slate-50 flex items-center justify-between">
              <span className="text-[11px] font-bold text-slate-500">最近上传批次</span>
              {batchFilter && (
                <button onClick={() => setBatchFilter('')} className="text-[10px] font-bold text-blue-500">取消筛选</button>
              )}
            </div>
            <div className="overflow-x-auto">
              <table className="w-full text-[11px]">
                <thead className="text-slate-400 font-bold bg-slate-50/40">
                  <tr>
                    <th className="px-3 py-2 text-left">导入时间</th>
                    <th className="px-3 py-2 text-right">总数</th>
                    <th className="px-3 py-2 text-right">内部</th>
                    <th className="px-3 py-2 text-right">外部</th>
                    <th className="px-3 py-2 text-right">电量(度)</th>
                    <th className="px-3 py-2 text-right">费用(元)</th>
                    <th className="px-3 py-2 text-right">批次</th>
                  </tr>
                </thead>
                <tbody>
                  {batches.map(b => (
                    <tr
                      key={b.batch_id}
                      onClick={() => setBatchFilter(batchFilter === b.batch_id ? '' : b.batch_id)}
                      className={`border-t border-slate-100 cursor-pointer transition-colors ${batchFilter === b.batch_id ? 'bg-blue-50/40' : 'hover:bg-slate-50/60'}`}
                    >
                      <td className="px-3 py-2 text-slate-600 whitespace-nowrap">{(b.imported_at || '').replace('T', ' ').slice(0, 19)}</td>
                      <td className="px-3 py-2 text-right font-bold text-slate-700">{Number(b.records).toLocaleString()}</td>
                      <td className="px-3 py-2 text-right text-blue-600 font-bold">{Number(b.internal_count).toLocaleString()}</td>
                      <td className="px-3 py-2 text-right text-amber-600 font-bold">{Number(b.external_count).toLocaleString()}</td>
                      <td className="px-3 py-2 text-right font-bold text-slate-600 tabular-nums">{Number(b.total_kwh ?? 0).toLocaleString('zh-CN', { maximumFractionDigits: 1 })}</td>
                      <td className="px-3 py-2 text-right font-bold text-slate-600 tabular-nums">¥{Number(b.total_fee ?? 0).toLocaleString('zh-CN', { maximumFractionDigits: 2 })}</td>
                      <td className="px-3 py-2 text-right text-slate-300 font-mono text-[10px]">{b.batch_id.slice(0, 12)}</td>
                    </tr>
                  ))}
                </tbody>
              </table>
            </div>
          </section>
        )}

        {/* 列表 */}
        <section className="bg-white rounded-2xl border border-slate-100 shadow-sm overflow-hidden">
          <div className="px-3 py-2 bg-slate-50 flex items-center gap-2 flex-wrap">
            <span className="text-[11px] font-bold text-slate-500">最新记录</span>
            <span className="text-[10px] font-bold text-slate-400">共 {total.toLocaleString()} 条</span>
            <div className="flex-1" />
            <input
              type="text"
              value={searchInput}
              onChange={(e) => setSearchInput(e.target.value)}
              onKeyDown={(e) => { if (e.key === 'Enter') setSearch(searchInput); }}
              placeholder="搜索订单/车牌/电站"
              className="bg-white border border-slate-200 rounded-lg px-2 py-1 text-[11px] outline-none focus:ring-1 focus:ring-blue-500/20 w-44"
            />
            <div className="flex gap-1 bg-white p-0.5 rounded-lg border border-slate-200">
              {([['', '全部'], ['internal', '内部'], ['external', '外部']] as const).map(([k, label]) => (
                <button
                  key={k}
                  onClick={() => setFilter(k as typeof filter)}
                  className={`px-2 py-0.5 rounded text-[10px] font-bold transition-colors ${filter === k ? 'bg-blue-50 text-blue-600' : 'text-slate-500 hover:bg-slate-50'}`}
                >{label}</button>
              ))}
            </div>
          </div>
          <div className="overflow-x-auto">
            <table className="w-full text-[11px]">
              <thead className="bg-slate-50/40 text-slate-400 font-bold">
                <tr>
                  <th className="px-3 py-2 text-left whitespace-nowrap">充电时间</th>
                  <th className="px-3 py-2 text-left whitespace-nowrap">车牌</th>
                  <th className="px-3 py-2 text-center whitespace-nowrap">分类</th>
                  <th className="px-3 py-2 text-left">电站 / 终端</th>
                  <th className="px-3 py-2 text-right whitespace-nowrap">电量(度)</th>
                  <th className="px-3 py-2 text-right whitespace-nowrap">费用(元)</th>
                  <th className="px-3 py-2 text-right whitespace-nowrap">时长(分)</th>
                  <th className="px-3 py-2 text-left whitespace-nowrap">订单编号</th>
                </tr>
              </thead>
              <tbody>
                {items.map(it => (
                  <tr key={it.id} className="border-t border-slate-100 hover:bg-slate-50/60">
                    <td className="px-3 py-2 text-slate-600 whitespace-nowrap font-mono">{(it.start_time || '').replace('T', ' ').slice(0, 16)}</td>
                    <td className="px-3 py-2 font-bold text-slate-700 font-mono whitespace-nowrap">{it.plate || it.judged_plate || <span className="text-slate-300">—</span>}</td>
                    <td className="px-3 py-2 text-center">
                      <span className={`px-1.5 py-0.5 rounded text-[10px] font-bold border ${KIND_STYLE[it.vehicle_kind]}`}>
                        {KIND_LABEL[it.vehicle_kind]}
                      </span>
                    </td>
                    <td className="px-3 py-2 text-slate-600 truncate max-w-xs">{it.station_name || '—'}{it.terminal_name ? ` · ${it.terminal_name}` : ''}</td>
                    <td className="px-3 py-2 text-right text-slate-700 font-bold tabular-nums">{Number(it.kwh ?? 0).toFixed(2)}</td>
                    <td className="px-3 py-2 text-right text-slate-700 font-bold tabular-nums">{Number(it.fee ?? 0).toFixed(2)}</td>
                    <td className="px-3 py-2 text-right text-slate-500 tabular-nums">{it.duration_min ?? '—'}</td>
                    <td className="px-3 py-2 text-slate-400 font-mono text-[10px]">{it.order_no}</td>
                  </tr>
                ))}
                {items.length === 0 && (
                  <tr>
                    <td colSpan={8} className="px-3 py-8 text-center text-slate-300 text-[11px] font-bold">
                      <FileSpreadsheet size={18} className="mx-auto mb-2 text-slate-200" />
                      尚无记录，先上传一份 xlsx 试试
                    </td>
                  </tr>
                )}
              </tbody>
            </table>
          </div>
        </section>

        <RotatingFooterHint className="pb-4" />
      <FeedbackFab module="ele" />
    </PageFrame>
  );
}

function Stat({ label, value, color }: { label: string; value: number; color: string }) {
  return (
    <div className="bg-slate-50 rounded-lg px-2 py-1.5">
      <div className="text-[9px] text-slate-400 uppercase font-bold">{label}</div>
      <div className={`text-sm font-black tabular-nums ${color}`}>{value}</div>
    </div>
  );
}

function KpiCard({ icon, label, value, accent = 'slate' }: { icon: React.ReactNode; label: string; value: string; accent?: 'slate' | 'blue' | 'amber' }) {
  const accentMap: Record<string, string> = {
    slate: 'text-slate-700',
    blue: 'text-blue-600',
    amber: 'text-amber-600',
  };
  return (
    <div className="bg-white rounded-xl border border-slate-100 shadow-sm p-3">
      <div className="flex items-center gap-1 text-[10px] font-bold text-slate-400 uppercase">
        <span className={accentMap[accent]}>{icon}</span>
        <span>{label}</span>
      </div>
      <div className={`text-base font-black tabular-nums leading-tight mt-0.5 ${accentMap[accent]}`}>{value}</div>
    </div>
  );
}
