import { useEffect, useState } from 'react';
import { useSearchParams } from 'react-router-dom';
import {
  Badge,
  Button,
  Descriptions,
  Drawer,
  Image,
  Input,
  Modal,
  Space,
  Table,
  Tabs,
  Tag,
  Typography,
  message,
} from 'antd';
import type { ColumnsType } from 'antd/es/table';
import type {
  StoreInfoChangeFieldDiff,
  StoreInfoChangeRequestDto,
  StoreInfoChangeStatus,
  StorePackageAuditSummaryDto,
  StorePackageChangeRequestDto,
  StorePackageChangeStatus,
} from '@dukang/shared-types';
import {
  STORE_INFO_CHANGE_STATUS_LABELS,
  STORE_INFO_CHANGEABLE_FIELD_LABELS,
} from '@dukang/shared-types';
import { request, type Paginated } from '../lib/api';
import { notifyPackageAuditChanged } from '../lib/admin-events';
import { fmtTime } from '../lib/constants';
import StorePackageAuditPanel from '../components/StorePackageAuditPanel';
import { useAdminListColumns } from '../lib/useAdminListColumns';
import { AdminListHeader } from '../components/AdminListHeader';
import { AdminPrimaryLink } from '../components/AdminPrimaryLink';

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

function fmtFieldValue(field: string, v: unknown): string {
  if (v == null || String(v).trim() === '') return '（空）';
  if (field === 'avgPrice' || field === 'latitude' || field === 'longitude') {
    return String(v);
  }
  if (field === 'envPhotoUrls' && Array.isArray(v)) {
    return `${v.length} 张`;
  }
  if (field === 'coverUrl') return '见对比图';
  return String(v);
}

function InfoChangeImageDiff({
  field,
  live,
  proposed,
  imageSize = 72,
}: {
  field: string;
  live: unknown;
  proposed: unknown;
  imageSize?: number;
}) {
  const liveUrls =
    field === 'coverUrl'
      ? [String(live || '').trim()].filter(Boolean)
      : Array.isArray(live)
        ? live.map((u) => String(u || '').trim()).filter(Boolean)
        : [];
  const proposedUrls =
    field === 'coverUrl'
      ? [String(proposed || '').trim()].filter(Boolean)
      : Array.isArray(proposed)
        ? proposed.map((u) => String(u || '').trim()).filter(Boolean)
        : [];

  return (
    <div style={{ display: 'flex', gap: 16, flexWrap: 'wrap' }}>
      <div>
        <Typography.Text type="secondary" style={{ display: 'block', marginBottom: 6 }}>
          变更前
        </Typography.Text>
        {liveUrls.length ? (
          <Image.PreviewGroup>
            <Space wrap size={8}>
              {liveUrls.map((url) => (
                <Image key={`live-${url}`} src={url} width={imageSize} height={imageSize} style={{ objectFit: 'cover', borderRadius: 4 }} />
              ))}
            </Space>
          </Image.PreviewGroup>
        ) : (
          <Typography.Text type="secondary">（空）</Typography.Text>
        )}
      </div>
      <div>
        <Typography.Text type="secondary" style={{ display: 'block', marginBottom: 6 }}>
          变更后
        </Typography.Text>
        {proposedUrls.length ? (
          <Image.PreviewGroup>
            <Space wrap size={8}>
              {proposedUrls.map((url) => (
                <Image key={`new-${url}`} src={url} width={imageSize} height={imageSize} style={{ objectFit: 'cover', borderRadius: 4 }} />
              ))}
            </Space>
          </Image.PreviewGroup>
        ) : (
          <Typography.Text type="secondary">（空）</Typography.Text>
        )}
      </div>
    </div>
  );
}

function InfoChangeAuditPanel({
  initialRequestId,
}: {
  initialRequestId?: string | null;
}) {
  const [loading, setLoading] = useState(false);
  const [items, setItems] = useState<StoreInfoChangeRequestDto[]>([]);
  const [total, setTotal] = useState(0);
  const [page, setPage] = useState(1);
  const [status, setStatus] = useState<string>('PENDING');
  const [pendingCount, setPendingCount] = useState(0);
  const [detailOpen, setDetailOpen] = useState(false);
  const [detailLoading, setDetailLoading] = useState(false);
  const [detail, setDetail] = useState<(StoreInfoChangeRequestDto & { diffs?: StoreInfoChangeFieldDiff[] }) | null>(null);
  const [rejectOpen, setRejectOpen] = useState(false);
  const [rejectReason, setRejectReason] = useState('');
  const [activeId, setActiveId] = useState<string | null>(null);
  const [infoFullscreen, setInfoFullscreen] = useState(false);

  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<{ items: StoreInfoChangeRequestDto[]; total: number; page?: number }>(
          `/admin/store-info-change-requests?${qs}`,
        ),
        request<{ pendingCount: number }>('/admin/store-info-change-requests/summary'),
      ]);
      setItems(data.items);
      setTotal(data.total);
      setPage(data.page ?? nextPage);
      setPendingCount(summary.pendingCount ?? 0);
    } catch (e) {
      message.error(e instanceof Error ? e.message : '加载失败');
    } finally {
      setLoading(false);
    }
  }

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

  useEffect(() => {
    if (initialRequestId) void openDetail(initialRequestId);
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, []);

  async function openDetail(id: string) {
    setDetailOpen(true);
    setDetailLoading(true);
    setDetail(null);
    try {
      const data = await request<StoreInfoChangeRequestDto & { diffs?: StoreInfoChangeFieldDiff[] }>(
        `/admin/store-info-change-requests/${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-info-change-requests/${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 columns: ColumnsType<StoreInfoChangeRequestDto> = [
    {
      title: '门店',
      dataIndex: 'storeName',
      render: (_, row) => (
        <AdminPrimaryLink onClick={() => void openDetail(row.id)}>
          {row.storeName || row.storeId}
        </AdminPrimaryLink>
      ),
    },
    {
      title: '状态',
      dataIndex: 'status',
      render: (v: StoreInfoChangeStatus) => (
        <Tag>{STORE_INFO_CHANGE_STATUS_LABELS[v] ?? v}</Tag>
      ),
    },
    {
      title: '变更字段',
      render: (_, row) =>
        row.changedFields?.length
          ? row.changedFields.map((f) => (
              <Tag key={f}>{STORE_INFO_CHANGEABLE_FIELD_LABELS[f as keyof typeof STORE_INFO_CHANGEABLE_FIELD_LABELS] ?? f}</Tag>
            ))
          : '—',
    },
    {
      title: '提交方',
      render: (_, row) =>
        row.submitterType === 'PARTNER' ? '合伙人' : row.submitterType === 'SHOP' ? '门店' : '总部',
    },
    { 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>
      <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]}>
                {STORE_INFO_CHANGE_STATUS_LABELS.PENDING}
              </Badge>
            ) : s ? (
              STORE_INFO_CHANGE_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={infoFullscreen ? '100%' : 680}
        open={detailOpen}
        onClose={() => {
          setDetailOpen(false);
          setInfoFullscreen(false);
        }}
        extra={
          <Space>
            <Button onClick={() => setInfoFullscreen((v) => !v)}>
              {infoFullscreen ? '退出全屏' : '全屏查看'}
            </Button>
            {detail?.status === 'PENDING' ? (
              <>
                <Button onClick={() => void audit(detail.id, 'APPROVE')}>通过</Button>
                <Button
                  danger
                  onClick={() => {
                    setActiveId(detail.id);
                    setRejectReason('');
                    setRejectOpen(true);
                  }}
                >
                  驳回
                </Button>
              </>
            ) : null}
          </Space>
        }
      >
        {detailLoading ? (
          <Typography.Text type="secondary">加载中…</Typography.Text>
        ) : detail ? (
          <>
            <Space style={{ marginBottom: 16 }} wrap>
              <Tag>{STORE_INFO_CHANGE_STATUS_LABELS[detail.status]}</Tag>
              <Typography.Text type="secondary">
                提交方：{detail.submitterType === 'PARTNER' ? '合伙人' : detail.submitterType === 'SHOP' ? '门店' : '总部'} · {fmtTime(detail.createdAt)}
              </Typography.Text>
            </Space>
            {detail.rejectReason ? (
              <Typography.Paragraph type="danger">驳回原因：{detail.rejectReason}</Typography.Paragraph>
            ) : null}
            {detail.diffs && detail.diffs.length ? (
              <Descriptions column={1} bordered size="small">
                {detail.diffs.map((d) => (
                  <Descriptions.Item
                    key={d.field}
                    label={STORE_INFO_CHANGEABLE_FIELD_LABELS[d.field] ?? d.field}
                  >
                    {d.field === 'coverUrl' || d.field === 'envPhotoUrls' ? (
                      <InfoChangeImageDiff
                        field={d.field}
                        live={d.live}
                        proposed={d.proposed}
                        imageSize={infoFullscreen ? 160 : 72}
                      />
                    ) : (
                      <span>
                        <Typography.Text delete type="secondary">
                          {fmtFieldValue(d.field, d.live)}
                        </Typography.Text>
                        <Typography.Text type="secondary"> → </Typography.Text>
                        <Typography.Text strong>
                          {fmtFieldValue(d.field, d.proposed)}
                        </Typography.Text>
                      </span>
                    )}
                  </Descriptions.Item>
                ))}
              </Descriptions>
            ) : (
              <Typography.Text type="secondary">无变更字段明细</Typography.Text>
            )}
          </>
        ) : 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>
  );
}

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 [activeRequestId, setActiveRequestId] = useState<string | null>(null);
  const [drawerTitle, setDrawerTitle] = useState('套餐变更详情');
  const [packageFullscreen, setPackageFullscreen] = useState(false);

  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]);

  const [searchParams] = useSearchParams();
  const initialTab = searchParams.get('tab') === 'info' ? 'info' : 'package';
  const [activeTab, setActiveTab] = useState<string>(initialTab);
  const infoRequestId = searchParams.get('infoRequestId');
  useEffect(() => {
    const rid = searchParams.get('requestId');
    if (rid) {
      setActiveRequestId(rid);
      setDetailOpen(true);
    }
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, []);

  function openDetail(id: string) {
    setActiveRequestId(id);
    setDrawerTitle('套餐变更详情');
    setDetailOpen(true);
  }

  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 baseColumns: ColumnsType<StorePackageChangeRequestDto> = [
    {
      title: '门店',
      dataIndex: 'storeName',
      render: (_, row) => (
        <AdminPrimaryLink onClick={() => void openDetail(row.id)}>
          {row.storeName || row.storeId}
        </AdminPrimaryLink>
      ),
    },
    {
      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={() => 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>
      ),
    },
  ];

  const { columns, settingsButton, settingsModal } = useAdminListColumns('store-package-audits', baseColumns, {
    page,
    pageSize: 20,
  });

  return (
    <div>
      {settingsModal}
      <AdminListHeader title="审核通知" settings={settingsButton} />
      <Tabs
        activeKey={activeTab}
        onChange={setActiveTab}
        items={[
          {
            key: 'package',
            label: '套餐审核',
            children: (
              <>
                <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),
                  }}
                />
              </>
            ),
          },
          {
            key: 'info',
            label: '信息变更',
            children: <InfoChangeAuditPanel initialRequestId={infoRequestId} />,
          },
        ]}
      />

      <Drawer
        title={drawerTitle}
        width={packageFullscreen ? '100%' : 880}
        open={detailOpen}
        onClose={() => {
          setDetailOpen(false);
          setPackageFullscreen(false);
        }}
        destroyOnClose
        extra={
          <Button onClick={() => setPackageFullscreen((v) => !v)}>
            {packageFullscreen ? '退出全屏' : '全屏查看'}
          </Button>
        }
      >
        {activeRequestId ? (
          <StorePackageAuditPanel
            requestId={activeRequestId}
            fullscreen={packageFullscreen}
            onAudited={() => {
              setDetailOpen(false);
              void reload(page, status);
            }}
            onDetailLoaded={(d) => {
              if (d) setDrawerTitle(`${d.storeName || d.storeId} · 套餐变更`);
            }}
          />
        ) : 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>
  );
}

