'use client';

import { useEffect, useMemo, useRef, useState } from 'react';
import { useRouter } from 'next/navigation';
import { CalendarClock, Loader2, ShieldCheck, Sparkles, TriangleAlert } from 'lucide-react';
import { RouteGuard, useHasPermission } from '@/components/auth/Guard';
import { XiaobaoWarningCard } from '@/components/xiaobao-warning/XiaobaoWarningCard';
import { useXiaobaoWarningRisks } from '@/hooks/useXiaobaoWarningRisks';
import { useAuthStore } from '@/stores/useAuthStore';
import { useXiaobaoWarningReadStore } from '@/stores/useXiaobaoWarningReadStore';
import type { XiaobaoRiskLevel, XiaobaoVersionRisk } from '@/lib/xiaobao-risk';
import { buildRiskInsightSignature, findPreviousRiskSnapshot, requestRiskInsight, shouldRequestRiskInsightWithRequestGate } from '@/lib/xiaobao-risk-ai';
import { buildRiskSignature, findLatestDailySnapshot, shouldSaveRiskSnapshot } from '@/lib/xiaobao-risk-trend';
import { attachXiaobaoRiskSuggestion, buildXiaobaoRiskInsightPendingKey } from '@/lib/xiaobao-risk-suggestion';
import {
  filterXiaobaoRiskWarnings,
  formatRemainingWork,
  isXiaobaoWarningUpdated,
  shouldSkipXiaobaoRiskInsightRequestForReadState,
  sanitizeRiskInsight,
} from '@/lib/xiaobao-warning-view';
import { formatDateTime } from '@/lib/format';

const RISK_LEVEL_LABEL: Record<XiaobaoRiskLevel, string> = {
  on_track: '按期',
  attention: '关注',
  at_risk: '有风险',
  likely_delayed: '大概率延期',
  blocked: '阻塞',
};

const RISK_LEVEL_STYLE: Record<XiaobaoRiskLevel, string> = {
  on_track: 'border-emerald-200 bg-emerald-50 text-emerald-700',
  attention: 'border-amber-200 bg-amber-50 text-amber-700',
  at_risk: 'border-orange-200 bg-orange-50 text-orange-700',
  likely_delayed: 'border-red-200 bg-red-50 text-red-700',
  blocked: 'border-zinc-900 bg-zinc-900 text-white',
};

type FilterOption = { id: string; label: string };

export default function XiaobaoWarningPage() {
  return (
    <RouteGuard permission="xiaobao.warning:view">
      <XiaobaoWarningContent />
    </RouteGuard>
  );
}

function XiaobaoWarningContent() {
  const router = useRouter();
  const canManage = useHasPermission('xiaobao.warning:manage');
  const user = useAuthStore((s) => s.user);
  const {
    risks,
    snapshots,
    insights,
    pendingInsightKeys,
    insightRequestAttempts,
    riskDataLoaded,
    saveSnapshot,
    saveInsight,
    beginInsightUpdate,
    finishInsightUpdate,
    today,
  } = useXiaobaoWarningRisks({ loadRiskCache: true });
  const { readStates, readStateLoaded, fetchReadStates, markRiskRead } = useXiaobaoWarningReadStore();
  const [selectedRiskId, setSelectedRiskId] = useState<string | null>(null);
  const [selectedProductId, setSelectedProductId] = useState('');
  const [selectedProjectId, setSelectedProjectId] = useState('');
  const savedSnapshotKeysRef = useRef(new Set<string>());
  const requestedInsightKeysRef = useRef(new Set<string>());

  useEffect(() => {
    if (user?.id) fetchReadStates();
  }, [fetchReadStates, user?.id]);

  useEffect(() => {
    risks.forEach((risk) => {
      const snapshot = { ...risk.currentSnapshot, createdAt: new Date().toISOString() };
      const previousToday = findLatestDailySnapshot(snapshots, snapshot.versionId, snapshot.date);
      if (!shouldSaveRiskSnapshot(snapshot, previousToday)) return;
      const key = `${snapshot.versionId}:${snapshot.date}:${buildRiskSignature(snapshot)}`;
      if (savedSnapshotKeysRef.current.has(key)) return;
      savedSnapshotKeysRef.current.add(key);
      saveSnapshot(snapshot).catch(() => {
        savedSnapshotKeysRef.current.delete(key);
      });
    });
  }, [risks, saveSnapshot, snapshots]);

  useEffect(() => {
    risks.forEach((risk) => {
      if (shouldSkipXiaobaoRiskInsightRequestForReadState(risk, readStates, user?.id, readStateLoaded)) return;
      const previous = findPreviousRiskSnapshot(snapshots, risk.versionId, today);
      const key = buildXiaobaoRiskInsightPendingKey(risk);
      if (!shouldRequestRiskInsightWithRequestGate({
        riskCacheLoaded: riskDataLoaded,
        cache: insights,
        current: risk,
        previous,
        lastRequestedAt: insightRequestAttempts[key],
      })) return;
      const signature = buildRiskInsightSignature(risk);
      if (pendingInsightKeys.includes(key)) return;
      if (requestedInsightKeysRef.current.has(key)) return;
      requestedInsightKeysRef.current.add(key);
      beginInsightUpdate(key);
      requestRiskInsight(risk).then((response) => {
        if (!response.ok) return;
        return saveInsight({
          versionId: risk.versionId,
          riskSignature: signature,
          insight: sanitizeRiskInsight(response.result),
          generatedAt: new Date().toISOString(),
          providerInfo: { model: response.meta.model },
        }).catch(() => {});
      }).catch(() => {}).finally(() => {
        finishInsightUpdate(key);
      });
    });
  }, [
    beginInsightUpdate,
    finishInsightUpdate,
    insights,
    insightRequestAttempts,
    pendingInsightKeys,
    readStateLoaded,
    readStates,
    riskDataLoaded,
    risks,
    saveInsight,
    snapshots,
    today,
    user?.id,
  ]);

  const risksWithInsight = useMemo(() => risks.map((risk) => attachXiaobaoRiskSuggestion(risk, {
    insights,
    pendingInsightKeys,
    pendingInsightAttempts: insightRequestAttempts,
  })), [insightRequestAttempts, insights, pendingInsightKeys, risks]);

  const warningRisks = useMemo(() => filterXiaobaoRiskWarnings(risksWithInsight), [risksWithInsight]);
  const productOptions = useMemo(() => buildProductOptions(warningRisks), [warningRisks]);
  const projectOptions = useMemo(
    () => buildProjectOptions(warningRisks, selectedProductId),
    [selectedProductId, warningRisks],
  );

  useEffect(() => {
    if (selectedProductId && !productOptions.some((option) => option.id === selectedProductId)) {
      setSelectedProductId('');
      setSelectedProjectId('');
    }
  }, [productOptions, selectedProductId]);

  useEffect(() => {
    if (selectedProjectId && !projectOptions.some((option) => option.id === selectedProjectId)) {
      setSelectedProjectId('');
    }
  }, [projectOptions, selectedProjectId]);

  const filteredRisks = useMemo(() => filterXiaobaoRiskWarnings(risksWithInsight, {
    productId: selectedProductId || undefined,
    projectId: selectedProjectId || undefined,
  }), [risksWithInsight, selectedProductId, selectedProjectId]);

  const updatedRiskIds = useMemo(() => {
    if (!user?.id || !readStateLoaded) return new Set<string>();
    return new Set(
      filteredRisks
        .filter((risk) => isXiaobaoWarningUpdated(risk, readStates, user.id))
        .map((risk) => risk.versionId),
    );
  }, [filteredRisks, readStateLoaded, readStates, user?.id]);

  useEffect(() => {
    if (filteredRisks.length === 0) {
      setSelectedRiskId(null);
      return;
    }
    if (!selectedRiskId || !filteredRisks.some((risk) => risk.versionId === selectedRiskId)) {
      setSelectedRiskId(filteredRisks[0].versionId);
    }
  }, [filteredRisks, selectedRiskId]);

  const selectedRisk = selectedRiskId
    ? filteredRisks.find((risk) => risk.versionId === selectedRiskId) ?? null
    : null;
  const avgConfidence = filteredRisks.length > 0
    ? Math.round(filteredRisks.reduce((sum, risk) => sum + risk.confidence, 0) / filteredRisks.length)
    : 0;

  const selectRisk = (risk: XiaobaoVersionRisk) => {
    setSelectedRiskId(risk.versionId);
    if (!user?.id) return;
    markRiskRead(user.id, risk).catch(() => {});
  };

  return (
    <div className="flex h-full flex-col bg-[var(--bg)]">
      <header className="flex h-14 shrink-0 items-center justify-between border-b border-[var(--line)] bg-[var(--bg-card)] px-5">
        <div className="flex min-w-0 items-center gap-3">
          <div className="flex h-8 w-8 items-center justify-center rounded-lg bg-[var(--accent-soft)] text-[var(--accent)]">
            <TriangleAlert className="h-4 w-4" />
          </div>
          <div className="min-w-0">
            <h1 className="truncate text-[15px] font-semibold text-[var(--ink)]">小宝预警</h1>
            <p className="truncate text-[11px] text-[var(--ink-muted)]">
              {canManage ? '管理视角：全部未结束版本' : '个人视角：我参与的未结束版本'}
            </p>
          </div>
        </div>
        <div className="flex items-center gap-3 text-[11px] text-[var(--ink-muted)]">
          {canManage && (
            <span className="inline-flex items-center gap-1 rounded-full bg-[var(--bg-subtle)] px-2 py-1">
              <ShieldCheck className="h-3.5 w-3.5" />
              管理权限
            </span>
          )}
          <div className="rounded-lg border border-[var(--line)] bg-[var(--bg-subtle)] px-3 py-1.5 text-right">
            <p>平均置信</p>
            <p className="text-[15px] font-semibold tabular-nums text-[var(--ink)]">{avgConfidence}%</p>
          </div>
        </div>
      </header>

      <main className="grid min-h-0 flex-1 grid-cols-1 overflow-hidden lg:grid-cols-[390px_minmax(0,1fr)]">
        <aside className="flex min-h-0 flex-col border-b border-[var(--line)] bg-[var(--bg-card)] lg:border-b-0 lg:border-r">
          <div className="shrink-0 border-b border-[var(--line)] p-4">
            <div className="grid grid-cols-2 gap-2">
              <SelectFilter
                label="产品"
                value={selectedProductId}
                allLabel="全部产品"
                options={productOptions}
                onChange={(value) => {
                  setSelectedProductId(value);
                  setSelectedProjectId('');
                }}
              />
              <SelectFilter
                label="项目"
                value={selectedProjectId}
                allLabel="全部项目"
                options={projectOptions}
                onChange={setSelectedProjectId}
              />
            </div>
            <p className="mt-3 text-[11px] text-[var(--ink-muted)]">
              当前显示 {filteredRisks.length} 个风险版本，系统会自动隐藏无风险版本。
            </p>
          </div>

          <div className="min-h-0 flex-1 overflow-y-auto p-3">
            {filteredRisks.length === 0 ? (
              <div className="rounded-lg border border-dashed border-[var(--line)] bg-[var(--bg)] p-8 text-center">
                <p className="text-[13px] font-medium text-[var(--ink-soft)]">暂无小宝预警</p>
                <p className="mt-1 text-[12px] text-[var(--ink-muted)]">当前筛选范围内没有风险版本。</p>
              </div>
            ) : (
              <div className="space-y-2">
                {filteredRisks.map((risk) => (
                  <XiaobaoWarningCard
                    key={risk.versionId}
                    active={risk.versionId === selectedRiskId}
                    risk={risk}
                    updated={updatedRiskIds.has(risk.versionId)}
                    onClick={() => selectRisk(risk)}
                  />
                ))}
              </div>
            )}
          </div>
        </aside>

        <section className="min-h-0 overflow-y-auto bg-[var(--bg)] p-5">
          {selectedRisk ? (
            <XiaobaoWarningDetailPanel
              risk={selectedRisk}
              onNavigate={() => router.push(`/versions/${selectedRisk.versionId}`)}
            />
          ) : (
            <div className="flex h-full items-center justify-center rounded-lg border border-dashed border-[var(--line)] bg-[var(--bg-card)] text-[13px] text-[var(--ink-muted)]">
              选择左侧风险版本查看详情
            </div>
          )}
        </section>
      </main>
    </div>
  );
}

function XiaobaoWarningDetailPanel({ risk, onNavigate }: { risk: XiaobaoVersionRisk; onNavigate: () => void }) {
  const [detailTab, setDetailTab] = useState<'reasons' | 'silent' | 'evidence'>('reasons');
  const evidence = risk.dailyEvidence;
  const evidenceItems = [
    ...(evidence?.todayDeliveries ?? []),
    ...(evidence?.todayProgress ?? []),
    ...(evidence?.todayCreations ?? []),
    ...(evidence?.todayRisks ?? []),
    ...(evidence?.progressNotes ?? []),
  ];

  return (
    <div className="mx-auto flex w-full max-w-5xl flex-col gap-5">
      <div className="flex flex-wrap items-start justify-between gap-3 border-b border-[var(--line)] pb-4">
        <div className="min-w-0">
          <p className="text-[12px] text-[var(--ink-muted)]">{risk.productName ?? '-'} / {risk.projectName ?? '-'}</p>
          <div className="mt-1 flex flex-wrap items-center gap-2">
            <h2 className="text-[20px] font-semibold text-[var(--ink)]">{risk.versionName}</h2>
            <RiskLevelBadge level={risk.riskLevel} />
          </div>
        </div>
        <button
          type="button"
          onClick={onNavigate}
          className="h-9 rounded-lg bg-[var(--accent)] px-4 text-[13px] font-medium text-white hover:bg-[var(--accent-hover)]"
        >
          打开版本详情
        </button>
      </div>

      <div className="grid gap-3 md:grid-cols-4">
        <DetailMetric label="风险分" value={String(risk.riskScore)} tone={risk.riskScore >= 75 ? 'danger' : risk.riskScore >= 55 ? 'warn' : 'ok'} />
        <DetailMetric label="置信" value={`${risk.confidence}%`} tone={risk.confidence < 50 ? 'danger' : risk.confidence < 75 ? 'warn' : 'ok'} />
        <DetailMetric label="剩余工作量" value={formatRemainingWork(risk.remainingWorkHours)} tone={risk.remainingWorkHours > 0 ? 'warn' : 'ok'} />
        <DetailMetric label="预计延期" value={risk.delayDays > 0 ? `${risk.delayDays}天` : '0天'} tone={risk.delayDays > 0 ? 'danger' : 'ok'} />
      </div>

      <Section title="小宝建议">
        {risk.aiInsightUpdating && <InsightUpdatingNotice source={risk.aiInsightSource} />}
        {risk.aiInsight ? (
          <div className="space-y-3">
            <div className="rounded-lg border border-[var(--line)] bg-[var(--bg-card)] p-4">
              <p className="flex items-start gap-2 text-[13px] font-medium leading-6 text-[var(--ink)]">
                <Sparkles className="mt-1 h-4 w-4 shrink-0 text-[var(--accent)]" />
                <span>{risk.aiInsight.summary}</span>
              </p>
              <p className="mt-3 text-[13px] leading-6 text-[var(--ink-soft)]">{risk.aiInsight.forecast}</p>
              {risk.aiInsight.recommendedReleaseWindow && (
                <p className="mt-3 text-[13px] leading-6 text-[var(--accent)]">{risk.aiInsight.recommendedReleaseWindow}</p>
              )}
            </div>
            <div className="grid gap-2 md:grid-cols-2">
              {risk.aiInsight.suggestedActions.map((action) => (
                <div key={action} className="rounded-lg border border-[var(--line)] bg-[var(--bg-card)] p-3 text-[12px] leading-5 text-[var(--ink-soft)]">
                  {action}
                </div>
              ))}
            </div>
          </div>
        ) : (
          <Empty text="规则预警已生成，AI 解读会在触发条件满足时自动补充。" />
        )}
      </Section>

      <Section title="发版预测">
        <div className="rounded-lg border border-[var(--line)] bg-[var(--bg-card)] p-4 text-[13px] leading-6 text-[var(--ink-soft)]">
          <div className="grid gap-3 md:grid-cols-3">
            <p className="flex items-center gap-1.5">
              <CalendarClock className="h-4 w-4 text-[var(--ink-muted)]" />
              期望发版：{formatDateTime(risk.expectedReleaseDate)}
            </p>
            <p>预测可发：{formatDateTime(risk.forecastReleaseDate)}</p>
            <p>预计延期：{risk.delayDays > 0 ? `${risk.delayDays}天` : '0天'}</p>
          </div>
          <p className="mt-3 border-t border-[var(--line)] pt-3">{risk.trend.summary}</p>
        </div>
      </Section>

      <Section title="风险证据">
        <div className="rounded-lg border border-[var(--line)] bg-[var(--bg-card)]">
          <div className="flex flex-wrap gap-1 border-b border-[var(--line)] bg-[var(--bg-subtle)] p-2">
            <TabButton active={detailTab === 'reasons'} onClick={() => setDetailTab('reasons')}>
              风险原因 {risk.reasons.length}
            </TabButton>
            <TabButton active={detailTab === 'silent'} onClick={() => setDetailTab('silent')}>
              静默风险 {risk.silentRisks.length}
            </TabButton>
            <TabButton active={detailTab === 'evidence'} onClick={() => setDetailTab('evidence')}>
              日报与活动证据 {evidenceItems.length}
            </TabButton>
          </div>
          <div className="min-h-[220px] p-3">
            {detailTab === 'reasons' && (
              <div className="space-y-2">
                {risk.reasons.length === 0 ? <Empty text="暂无风险原因" /> : risk.reasons.map((reason) => (
                  <div key={reason.key} className="rounded-lg border border-[var(--line)] bg-[var(--bg)] p-3">
                    <div className="flex items-center justify-between gap-3">
                      <p className="text-[12px] font-medium text-[var(--ink)]">{reason.title}</p>
                      <span className="rounded-full bg-[var(--bg-subtle)] px-2 py-0.5 text-[10px] text-[var(--ink-muted)]">{reason.severity}</span>
                    </div>
                    <p className="mt-1 text-[12px] leading-5 text-[var(--ink-soft)]">{reason.detail}</p>
                  </div>
                ))}
              </div>
            )}

            {detailTab === 'silent' && (
              <div className="space-y-2">
                {risk.silentRisks.length === 0 ? <Empty text="暂无静默风险" /> : risk.silentRisks.map((item, index) => (
                  <div key={`${item.key}-${item.itemId ?? index}`} className="rounded-lg border border-amber-200 bg-amber-50 p-3">
                    <p className="text-[12px] font-medium text-amber-900">{item.title}</p>
                    <p className="mt-1 text-[12px] leading-5 text-amber-800">{item.detail}</p>
                  </div>
                ))}
              </div>
            )}

            {detailTab === 'evidence' && (
              <div className="space-y-2">
                {evidenceItems.length === 0 ? <Empty text="暂无近期日报或活动证据" /> : evidenceItems.map((item) => (
                  <div key={item.id} className="rounded-lg border border-[var(--line)] bg-[var(--bg)] p-3">
                    <p className="text-[12px] font-medium text-[var(--ink)]">{item.title}</p>
                    <p className="mt-1 text-[12px] leading-5 text-[var(--ink-soft)]">{item.summary}</p>
                    <p className="mt-1 text-[10px] text-[var(--ink-muted)]">{formatDateTime(item.occurredAt)}</p>
                  </div>
                ))}
              </div>
            )}
          </div>
        </div>
      </Section>
    </div>
  );
}

function InsightUpdatingNotice({ source }: { source?: XiaobaoVersionRisk['aiInsightSource'] }) {
  const detail = source === 'previous_ai'
    ? '当前先显示上一条建议，生成完成后会自动替换。'
    : '当前先显示规则建议，生成完成后会自动替换。';
  return (
    <div className="flex items-start gap-2 rounded-lg border border-amber-200 bg-amber-50 px-3 py-2 text-[12px] leading-5 text-amber-800">
      <Loader2 className="mt-0.5 h-3.5 w-3.5 shrink-0 animate-spin" />
      <span>新的小宝建议更新中。{detail}</span>
    </div>
  );
}

function RiskLevelBadge({ level }: { level: XiaobaoRiskLevel }) {
  return (
    <span className={`inline-flex shrink-0 rounded-full border px-2 py-0.5 text-[11px] font-medium ${RISK_LEVEL_STYLE[level]}`}>
      {RISK_LEVEL_LABEL[level]}
    </span>
  );
}

function DetailMetric({ label, value, tone }: { label: string; value: string; tone: 'ok' | 'warn' | 'danger' }) {
  const toneClass = tone === 'danger' ? 'text-red-600' : tone === 'warn' ? 'text-amber-600' : 'text-emerald-600';
  return (
    <div className="rounded-lg border border-[var(--line)] bg-[var(--bg-card)] p-3">
      <p className="text-[11px] text-[var(--ink-muted)]">{label}</p>
      <p className={`mt-1 text-[18px] font-semibold tabular-nums ${toneClass}`}>{value}</p>
    </div>
  );
}

function SelectFilter({
  label,
  value,
  allLabel,
  options,
  onChange,
}: {
  label: string;
  value: string;
  allLabel: string;
  options: FilterOption[];
  onChange: (value: string) => void;
}) {
  return (
    <label className="block">
      <span className="mb-1 block text-[11px] font-medium text-[var(--ink-muted)]">{label}</span>
      <select
        value={value}
        onChange={(event) => onChange(event.target.value)}
        className="h-8 w-full rounded-lg border border-[var(--line)] bg-[var(--bg)] px-2 text-[12px] text-[var(--ink)] outline-none focus:border-[var(--accent)] focus:ring-2 focus:ring-[var(--accent-ring)]"
      >
        <option value="">{allLabel}</option>
        {options.map((option) => (
          <option key={option.id} value={option.id}>{option.label}</option>
        ))}
      </select>
    </label>
  );
}

function TabButton({ active, onClick, children }: { active: boolean; onClick: () => void; children: React.ReactNode }) {
  return (
    <button
      type="button"
      onClick={onClick}
      className={`h-8 rounded-md px-3 text-[12px] transition-colors ${
        active
          ? 'bg-[var(--bg-card)] text-[var(--accent)] shadow-sm'
          : 'text-[var(--ink-soft)] hover:bg-[var(--bg-card)] hover:text-[var(--ink)]'
      }`}
    >
      {children}
    </button>
  );
}

function Section({ title, children }: { title: string; children: React.ReactNode }) {
  return (
    <section>
      <h3 className="mb-2 text-[12px] font-semibold text-[var(--ink)]">{title}</h3>
      <div className="space-y-2">{children}</div>
    </section>
  );
}

function Empty({ text }: { text: string }) {
  return (
    <div className="rounded-lg border border-dashed border-[var(--line)] bg-[var(--bg-card)] p-3 text-[12px] text-[var(--ink-muted)]">
      {text}
    </div>
  );
}

function buildProductOptions(risks: XiaobaoVersionRisk[]): FilterOption[] {
  return uniqueOptions(risks.map((risk) => ({
    id: risk.productId ?? '',
    label: risk.productName ?? '未关联产品',
  })));
}

function buildProjectOptions(risks: XiaobaoVersionRisk[], productId: string): FilterOption[] {
  const scoped = productId ? risks.filter((risk) => risk.productId === productId) : risks;
  return uniqueOptions(scoped.map((risk) => ({
    id: risk.projectId ?? '',
    label: risk.projectName ?? '未关联项目',
  })));
}

function uniqueOptions(options: FilterOption[]): FilterOption[] {
  const map = new Map<string, string>();
  options.forEach((option) => {
    if (!option.id || map.has(option.id)) return;
    map.set(option.id, option.label);
  });
  return Array.from(map, ([id, label]) => ({ id, label })).sort((a, b) => a.label.localeCompare(b.label));
}
