import { useEffect, useState } from 'react';
import { useSearchParams } from 'react-router-dom';
import {
  Badge,
  Button,
  Drawer,
  Image,
  Input,
  Modal,
  Space,
  Table,
  Tag,
  Typography,
  message,
} from 'antd';
import type { ColumnsType } from 'antd/es/table';
import type {
  StorePackageAuditDetailDto,
  StorePackageAuditSummaryDto,
  StorePackageChangeRequestDto,
  StorePackageChangeStatus,
  StorePackageItemDto,
  StorePackageViewDto,
} from '@dukang/shared-types';
import { normalizeStorePackageImageUrls } from '@dukang/shared-types';
import { request, type Paginated } from '../lib/api';
import { notifyPackageAuditChanged } from '../lib/admin-events';
import { fmtTime } from '../lib/constants';

const HQ_PACKAGE_STATUS_LABELS: Record<StorePackageChangeStatus, string> = {
  PENDING: '待审核',
  APPROVED: '已通过',
  REJECTED: '已驳回',
};

function packageKey(pkg: StorePackageItemDto | StorePackageViewDto, index: number) {
  const name = String(pkg.name ?? '').trim();
  return name ? `name:${name}` : `idx:${index}`;
}

function imageSignature(pkg: StorePackageItemDto | StorePackageViewDto) {
  return normalizeStorePackageImageUrls(pkg).join('|');
}

function diffPackages(live: StorePackageViewDto[], proposed: StorePackageItemDto[]) {
  const liveMap = new Map(live.map((p, i) => [packageKey(p, i), p]));
  const proposedMap = new Map(proposed.map((p, i) => [packageKey(p, i), p]));
  const keys = new Set([...liveMap.keys(), ...proposedMap.keys()]);
  const rows: Array<{
    key: string;
    change: 'added' | 'removed' | 'changed' | 'unchanged';
    live?: StorePackageViewDto;
    proposed?: StorePackageItemDto;
  }> = [];

  for (const key of keys) {
    const l = liveMap.get(key);
    const p = proposedMap.get(key);
    if (l && !p) {
      rows.push({ key, change: 'removed', live: l });
    } else if (!l && p) {
      rows.push({ key, change: 'added', proposed: p });
    } else if (l && p) {
      const changed =
        l.price !== p.price ||
        l.dishes !== p.dishes ||
        (l.usableTime ?? '') !== (p.usableTime ?? '') ||
        (l.otherNotes ?? '') !== (p.otherNotes ?? '') ||
        imageSignature(l) !== imageSignature(p);
      rows.push({ key, change: changed ? 'changed' : 'unchanged', live: l, proposed: p });
    }
  }
  return rows;
}

const CHANGE_LABELS = {
  added: { text: '新增', color: 'green' },
  removed: { text: '删除', color: 'red' },
  changed: { text: '变更', color: 'orange' },
  unchanged: { text: '未变', color: 'default' },
} as const;

function PackageDetailCard({
  title,
  pkg,
  change,
}: {
  title?: string;
  pkg: StorePackageItemDto | StorePackageViewDto;
  change?: keyof typeof CHANGE_LABELS;
}) {
  const images = normalizeStorePackageImageUrls(pkg);
  const meta = change ? CHANGE_LABELS[change] : null;
  return (
    <div
      style={{
        marginBottom: 12,
        padding: 12,
        border: '1px solid #f0f0f0',
        borderRadius: 8,
        background: '#fafafa',
      }}
    >
      <Space style={{ marginBottom: 8 }} wrap>
        {title ? (
          <Typography.Text type="secondary">{title}</Typography.Text>
        ) : null}
        {meta ? <Tag color={meta.color}>{meta.text}</Tag> : null}
      </Space>
      <div style={{ marginBottom: 8 }}>
        <strong>{pkg.name}</strong>
        <span style={{ marginLeft: 8 }}>¥{pkg.price}</span>
      </div>
      <Typography.Paragraph className="admin-package-audit-text" style={{ marginBottom: 8 }}>
        {pkg.dishes || '—'}
      </Typography.Paragraph>
      {pkg.usableTime ? (
        <Typography.Paragraph
          type="secondary"
          className="admin-package-audit-text"
          style={{ marginBottom: 4 }}
        >
          可用时间：{pkg.usableTime}
        </Typography.Paragraph>
      ) : null}
      {pkg.otherNotes ? (
        <Typography.Paragraph
          type="secondary"
          className="admin-package-audit-text"
          style={{ marginBottom: 8 }}
        >
          其他说明：{pkg.otherNotes}
        </Typography.Paragraph>
      ) : null}
      {images.length ? (
        <Image.PreviewGroup>
          <Space wrap size={8}>
            {images.map((url) => (
              <Image
                key={url}
                src={url}
                width={72}
                height={72}
                style={{ objectFit: 'cover', borderRadius: 4 }}
              />
            ))}
          </Space>
        </Image.PreviewGroup>
      ) : (
        <Typography.Text type="secondary">无套餐图片</Typography.Text>
      )}
    </div>
  );
}

export default function StorePackageAuditsPage() {
  const [loading, setLoading] = useState(false);
  const [items, setItems] = useState<StorePackageChangeRequestDto[]>([]);
  const [total, setTotal] = useState(0);
  const [page, setPage] = useState(1);
  const [status, setStatus] = useState<string>('PENDING');
  const [pendingCount, setPendingCount] = useState(0);
  const [rejectOpen, setRejectOpen] = useState(false);
  const [rejectReason, setRejectReason] = useState('');
  const [activeId, setActiveId] = useState<string | null>(null);
  const [detailOpen, setDetailOpen] = useState(false);
  const [detailLoading, setDetailLoading] = useState(false);
  const [detail, setDetail] = useState<StorePackageAuditDetailDto | null>(null);

  async function reload(nextPage = page, nextStatus = status) {
    setLoading(true);
    try {
      const qs = new URLSearchParams({
        page: String(nextPage),
        pageSize: '20',
      });
      if (nextStatus) qs.set('status', nextStatus);
      const [data, summary] = await Promise.all([
        request<Paginated<StorePackageChangeRequestDto>>(`/admin/store-package-audits?${qs}`),
        request<StorePackageAuditSummaryDto>('/admin/store-package-audits/summary'),
      ]);
      setItems(data.items);
      setTotal(data.total);
      setPage(data.page);
      setPendingCount(summary.pendingCount ?? 0);
    } catch (e) {
      message.error(e instanceof Error ? e.message : '加载失败');
    } finally {
      setLoading(false);
    }
  }

  useEffect(() => {
    void reload(1, status);
  }, [status]);

  // 从门店详情 / 门店列表跳转过来时，带 requestId 自动打开审核（对比）抽屉
  const [searchParams] = useSearchParams();
  useEffect(() => {
    const rid = searchParams.get('requestId');
    if (rid) void openDetail(rid);
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, []);

  async function openDetail(id: string) {
    setDetailOpen(true);
    setDetailLoading(true);
    setDetail(null);
    try {
      const data = await request<StorePackageAuditDetailDto>(`/admin/store-package-audits/${id}`);
      setDetail(data);
    } catch (e) {
      message.error(e instanceof Error ? e.message : '加载详情失败');
      setDetailOpen(false);
    } finally {
      setDetailLoading(false);
    }
  }

  async function audit(id: string, action: 'APPROVE' | 'REJECT', reason?: string) {
    try {
      await request(`/admin/store-package-audits/${id}/audit`, {
        method: 'PUT',
        body: JSON.stringify(
          action === 'REJECT' ? { action, rejectReason: reason } : { action },
        ),
      });
      message.success(action === 'APPROVE' ? '已通过' : '已驳回');
      setDetailOpen(false);
      notifyPackageAuditChanged();
      void reload(page, status);
    } catch (e) {
      message.error(e instanceof Error ? e.message : '操作失败');
    }
  }

  const diffRows = detail ? diffPackages(detail.livePackages ?? [], detail.packages ?? []) : [];
  const changeByKey = new Map(diffRows.map((row) => [row.key, row.change]));

  const columns: ColumnsType<StorePackageChangeRequestDto> = [
    { title: '门店', dataIndex: 'storeName', render: (_, row) => row.storeName || row.storeId },
    {
      title: '状态',
      dataIndex: 'status',
      render: (v: StorePackageChangeRequestDto['status']) => (
        <Tag>{HQ_PACKAGE_STATUS_LABELS[v] ?? v}</Tag>
      ),
    },
    {
      title: '套餐数',
      render: (_, row) => row.packages?.length ?? 0,
    },
    {
      title: '提交方',
      render: (_, row) => (row.submitterType === 'PARTNER' ? '合伙人' : '门店'),
    },
    { title: '提交时间', dataIndex: 'createdAt', render: (v) => fmtTime(String(v)) },
    {
      title: '操作',
      render: (_, row) => (
        <Space>
          <Button type="link" onClick={() => void openDetail(row.id)}>
            查看变更
          </Button>
          {row.status === 'PENDING' ? (
            <>
              <Button type="link" onClick={() => void audit(row.id, 'APPROVE')}>
                通过
              </Button>
              <Button
                type="link"
                danger
                onClick={() => {
                  setActiveId(row.id);
                  setRejectReason('');
                  setRejectOpen(true);
                }}
              >
                驳回
              </Button>
            </>
          ) : (
            row.rejectReason || null
          )}
        </Space>
      ),
    },
  ];

  return (
    <div>
      <Typography.Title level={4}>套餐变更审核</Typography.Title>
      <Space style={{ marginBottom: 16 }}>
        {(['PENDING', 'APPROVED', 'REJECTED', ''] as const).map((s) => (
          <Button key={s || 'all'} type={status === s ? 'primary' : 'default'} onClick={() => setStatus(s)}>
            {s === 'PENDING' ? (
              <Badge count={pendingCount} size="small" offset={[8, -2]}>
                {HQ_PACKAGE_STATUS_LABELS.PENDING}
              </Badge>
            ) : s ? (
              HQ_PACKAGE_STATUS_LABELS[s]
            ) : (
              '全部'
            )}
          </Button>
        ))}
      </Space>
      <Table
        rowKey="id"
        loading={loading}
        columns={columns}
        dataSource={items}
        pagination={{
          current: page,
          total,
          pageSize: 20,
          onChange: (p) => void reload(p, status),
        }}
      />

      <Drawer
        title={detail ? `${detail.storeName || detail.storeId} · 套餐变更` : '套餐变更详情'}
        width={880}
        open={detailOpen}
        onClose={() => setDetailOpen(false)}
        extra={
          detail?.status === 'PENDING' ? (
            <Space>
              <Button onClick={() => void audit(detail.id, 'APPROVE')}>通过</Button>
              <Button
                danger
                onClick={() => {
                  setActiveId(detail.id);
                  setRejectReason('');
                  setRejectOpen(true);
                }}
              >
                驳回
              </Button>
            </Space>
          ) : null
        }
      >
        {detailLoading ? (
          <Typography.Text type="secondary">加载中…</Typography.Text>
        ) : detail ? (
          <>
            <Space style={{ marginBottom: 16 }} wrap>
              <Tag>{HQ_PACKAGE_STATUS_LABELS[detail.status]}</Tag>
              <Typography.Text type="secondary">
                提交方：{detail.submitterType === 'PARTNER' ? '合伙人' : '门店'} · {fmtTime(detail.createdAt)}
              </Typography.Text>
            </Space>
            {detail.rejectReason ? (
              <Typography.Paragraph type="danger">驳回原因：{detail.rejectReason}</Typography.Paragraph>
            ) : null}
            <Typography.Paragraph type="secondary" style={{ marginBottom: 12 }}>
              线上已审核 {detail.livePackages?.length ?? 0} 条 · 待审核 {detail.packages?.length ?? 0} 条
            </Typography.Paragraph>
            <div className="admin-package-audit-cols">
              <div className="admin-package-audit-col">
                <Typography.Title level={5} style={{ marginTop: 0 }}>
                  线上已审核套餐
                </Typography.Title>
                {(detail.livePackages ?? []).length ? (
                  (detail.livePackages ?? []).map((pkg, index) => (
                    <PackageDetailCard
                      key={`live-${packageKey(pkg, index)}`}
                      title={`套餐 ${index + 1}`}
                      pkg={pkg}
                      change={changeByKey.get(packageKey(pkg, index))}
                    />
                  ))
                ) : (
                  <Typography.Text type="secondary">暂无线上套餐</Typography.Text>
                )}
              </div>
              <div className="admin-package-audit-col">
                <Typography.Title level={5} style={{ marginTop: 0 }}>
                  待审核套餐
                </Typography.Title>
                {(detail.packages ?? []).length ? (
                  (detail.packages ?? []).map((pkg, index) => (
                    <PackageDetailCard
                      key={`pending-${packageKey(pkg, index)}`}
                      title={`套餐 ${index + 1}`}
                      pkg={pkg}
                      change={changeByKey.get(packageKey(pkg, index))}
                    />
                  ))
                ) : (
                  <Typography.Text type="secondary">暂无待审核套餐</Typography.Text>
                )}
              </div>
            </div>
          </>
        ) : null}
      </Drawer>

      <Modal
        title="驳回套餐变更"
        open={rejectOpen}
        onCancel={() => setRejectOpen(false)}
        onOk={() => {
          if (!activeId) return;
          if (!rejectReason.trim()) {
            message.warning('请填写驳回原因');
            return;
          }
          void audit(activeId, 'REJECT', rejectReason.trim());
          setRejectOpen(false);
        }}
      >
        <Input.TextArea
          rows={3}
          value={rejectReason}
          placeholder="驳回原因"
          onChange={(e) => setRejectReason(e.target.value)}
        />
      </Modal>
    </div>
  );
}
