import { useState } from 'react';
import {
  Drawer, Form, Input, Modal, Select, Space, Tag, Timeline, Typography, message,
} from 'antd';
import { ProCard } from '@ant-design/pro-components';
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
import type { ColDef } from '@ag-grid-community/core';
import dayjs from 'dayjs';
import PageContainer from '@/components/common/PageContainer';
import SearchForm from '@/components/common/SearchForm';
import DataGrid from '@/components/common/DataGrid';
import PermissionButton from '@/components/common/PermissionButton';
import {
  clawbackReceivableApi,
  ClawbackReceivableRow,
  ClawbackReceivableDetail,
  ClawbackSearchParam,
} from '@/api/clawbackReceivable';
import { GRAY, RADIUS, SHADOW, COLOR_SUCCESS, COLOR_ERROR, COLOR_WARNING, COLOR_PRIMARY } from '@/theme/tokens';

const { Text } = Typography;

const fmt = (v: unknown) =>
  typeof v === 'number' ? v.toLocaleString() : (v as string | undefined) ?? '-';

const STATUS_COLOR: Record<string, string> = {
  OUTSTANDING: COLOR_ERROR,
  RECOVERING:  COLOR_WARNING,
  CLEARED:     COLOR_SUCCESS,
  WRITTEN_OFF: GRAY[400],
};

const STATUS_LABEL: Record<string, string> = {
  OUTSTANDING: '미회수',
  RECOVERING:  '회수중',
  CLEARED:     '상환완료',
  WRITTEN_OFF: '대손',
};

function StatusChip({ status, statusName }: { status: string; statusName?: string }) {
  const color = STATUS_COLOR[status] ?? GRAY[400];
  const label = statusName ?? STATUS_LABEL[status] ?? status;
  return (
    <Tag
      style={{
        color,
        background: `${color}1A`,
        border: `1px solid ${color}40`,
        borderRadius: RADIUS.sm,
        fontWeight: 600,
        fontSize: 12,
      }}
    >
      {label}
    </Tag>
  );
}

const GRID_COLS: ColDef<ClawbackReceivableRow>[] = [
  { field: 'agentName',          headerName: '설계사',   width: 130, pinned: 'left' },
  { field: 'originSettleMonth',  headerName: '발생월',   width: 110 },
  {
    field: 'originalAmount',
    headerName: '발생액',
    flex: 1,
    type: 'numericColumn',
    valueFormatter: (p) => fmt(p.value),
  },
  {
    field: 'recoveredAmount',
    headerName: '회수액',
    flex: 1,
    type: 'numericColumn',
    valueFormatter: (p) => fmt(p.value),
  },
  {
    field: 'balance',
    headerName: '잔액',
    flex: 1,
    type: 'numericColumn',
    valueFormatter: (p) => fmt(p.value),
  },
  {
    field: 'status',
    headerName: '상태',
    width: 120,
    cellRenderer: (p: { data: ClawbackReceivableRow }) =>
      p.data ? <StatusChip status={p.data.status} statusName={p.data.statusName} /> : null,
  },
  { field: 'lastRecoveryMonth', headerName: '최근회수월', width: 120 },
];

const MENU_CODE = 'CLAWBACK_RECEIVABLE';

export default function ClawbackReceivable() {
  const qc = useQueryClient();
  const [params, setParams] = useState<ClawbackSearchParam>({ pageSize: 200 });
  const [selectedRow, setSelectedRow] = useState<ClawbackReceivableRow | null>(null);
  const [drawerOpen, setDrawerOpen] = useState(false);
  const [writeOffOpen, setWriteOffOpen] = useState(false);
  const [writeOffForm] = Form.useForm();

  // ── 목록 조회 ──────────────────────────────────────
  const { data: listData, isLoading } = useQuery({
    queryKey: ['clawback-receivables', params],
    queryFn: () => clawbackReceivableApi.list(params),
    retry: false,
  });

  // ── 상세 조회 (행 클릭 시) ─────────────────────────
  const { data: detail, isLoading: detailLoading } = useQuery({
    queryKey: ['clawback-receivable', selectedRow?.receivableId],
    queryFn: () => clawbackReceivableApi.detail(selectedRow!.receivableId),
    enabled: !!selectedRow,
    retry: false,
  });

  // ── 대손/상환 처리 뮤테이션 ──────────────────────────
  const writeOffMutation = useMutation({
    mutationFn: ({ id, body }: { id: number; body: { status: 'CLEARED' | 'WRITTEN_OFF'; writeoffReason: string } }) =>
      clawbackReceivableApi.writeOff(id, body),
    onSuccess: () => {
      message.success('처리 완료');
      qc.invalidateQueries({ queryKey: ['clawback-receivables'] });
      qc.invalidateQueries({ queryKey: ['clawback-receivable', selectedRow?.receivableId] });
      setWriteOffOpen(false);
      writeOffForm.resetFields();
    },
  });

  const rows = listData?.list ?? [];

  // ── 합계행 ─────────────────────────────────────────
  const pinnedBottom =
    rows.length > 0
      ? ({
          agentName:       '합계',
          originalAmount:  rows.reduce((s, r) => s + (r.originalAmount ?? 0), 0),
          recoveredAmount: rows.reduce((s, r) => s + (r.recoveredAmount ?? 0), 0),
          balance:         rows.reduce((s, r) => s + (r.balance ?? 0), 0),
        } as Partial<ClawbackReceivableRow>)
      : undefined;

  const handleRowClick = (row: ClawbackReceivableRow) => {
    setSelectedRow(row);
    setDrawerOpen(true);
  };

  const handleExport = async () => {
    try {
      const res = await clawbackReceivableApi.export(params);
      const url = URL.createObjectURL(new Blob([res.data as BlobPart]));
      const a = document.createElement('a');
      a.href = url;
      a.download = `환수채권_${dayjs().format('YYYYMMDD')}.xlsx`;
      a.click();
      URL.revokeObjectURL(url);
    } catch {
      /* request.ts 처리 */
    }
  };

  const handleWriteOffSubmit = async () => {
    const values = await writeOffForm.validateFields();
    if (!selectedRow) return;
    writeOffMutation.mutate({
      id: selectedRow.receivableId,
      body: { status: values.status, writeoffReason: values.writeoffReason },
    });
  };

  const canWriteOff =
    selectedRow?.status === 'OUTSTANDING' || selectedRow?.status === 'RECOVERING';

  const cardStyle = {
    background: '#fff',
    borderRadius: RADIUS.lg,
    border: `1px solid ${GRAY[100]}`,
    boxShadow: SHADOW.sm,
  };

  return (
    <PageContainer
      title="환수채권관리"
      description="환수채권 이월/미수금 목록 조회 및 대손/상환 처리"
      extra={
        <PermissionButton menuCode={MENU_CODE} permCode="EXPORT" onClick={handleExport}>
          엑셀 다운로드
        </PermissionButton>
      }
    >
      <SearchForm
        conditions={[
          { type: 'text',  name: 'agentName',          label: '설계사명', span: 6 },
          { type: 'code',  name: 'status',              label: '상태',     span: 6, groupCode: 'CLAWBACK_RCV_STATUS' },
          { type: 'month', name: 'originSettleMonth',   label: '발생월',   span: 6 },
        ]}
        onSearch={(v) => setParams({ ...(v as ClawbackSearchParam), pageSize: 200 })}
        onReset={() => setParams({ pageSize: 200 })}
      />

      <ProCard style={cardStyle}>
        <DataGrid<ClawbackReceivableRow>
          rows={rows}
          columns={GRID_COLS}
          loading={isLoading}
          height={560}
          rowKey="receivableId"
          pinnedBottomRow={pinnedBottom}
          onSelectionChanged={(e) => {
            const sel = e.api.getSelectedRows();
            if (sel.length > 0) handleRowClick(sel[0]);
          }}
        />
      </ProCard>

      {/* ── 상세 Drawer ─────────────────────────────── */}
      <Drawer
        title="환수채권 상세"
        width={520}
        open={drawerOpen}
        onClose={() => setDrawerOpen(false)}
        extra={
          <PermissionButton
            menuCode={MENU_CODE}
            permCode="UPDATE"
            type="primary"
            danger
            disabled={!canWriteOff}
            onClick={() => setWriteOffOpen(true)}
          >
            대손/상환 처리
          </PermissionButton>
        }
      >
        {detailLoading || !detail ? (
          <Text style={{ color: GRAY[400] }}>불러오는 중...</Text>
        ) : (
          <DrawerContent detail={detail} />
        )}
      </Drawer>

      {/* ── 대손/상환 처리 모달 ──────────────────────── */}
      <Modal
        title="대손/상환 처리"
        open={writeOffOpen}
        onOk={handleWriteOffSubmit}
        onCancel={() => { setWriteOffOpen(false); writeOffForm.resetFields(); }}
        okText="처리"
        cancelText="취소"
        confirmLoading={writeOffMutation.isPending}
      >
        <Form form={writeOffForm} layout="vertical" style={{ marginTop: 16 }}>
          <Form.Item name="status" label="처리 유형" rules={[{ required: true, message: '처리 유형을 선택하세요' }]}>
            <Select placeholder="선택">
              <Select.Option value="CLEARED">상환완료 (직접 상환)</Select.Option>
              <Select.Option value="WRITTEN_OFF">대손 처리</Select.Option>
            </Select>
          </Form.Item>
          <Form.Item name="writeoffReason" label="사유" rules={[{ required: true, message: '사유를 입력하세요' }]}>
            <Input.TextArea rows={3} placeholder="처리 사유를 입력하세요" maxLength={300} showCount />
          </Form.Item>
        </Form>
      </Modal>
    </PageContainer>
  );
}

// ── 상세 내용 컴포넌트 ─────────────────────────────────

function DrawerContent({ detail }: { detail: ClawbackReceivableDetail }) {
  const fields: Array<{ label: string; value: React.ReactNode }> = [
    { label: '설계사',    value: detail.agentName },
    { label: '발생월',    value: detail.originSettleMonth },
    { label: '발생액',    value: fmt(detail.originalAmount) },
    { label: '회수액',    value: fmt(detail.recoveredAmount) },
    { label: '잔액',      value: fmt(detail.balance) },
    { label: '상태',      value: <StatusChip status={detail.status} statusName={detail.statusName} /> },
    { label: '최근회수월', value: detail.lastRecoveryMonth ?? '-' },
    { label: '등록일',    value: detail.createdAt ? dayjs(detail.createdAt).format('YYYY-MM-DD') : '-' },
  ];

  if (detail.writeoffReason) {
    fields.push({ label: '처리사유', value: detail.writeoffReason });
  }

  return (
    <>
      <div
        style={{
          display: 'grid',
          gridTemplateColumns: '100px 1fr',
          gap: '10px 12px',
          marginBottom: 24,
        }}
      >
        {fields.map(({ label, value }) => (
          <>
            <Text key={`lbl-${label}`} style={{ color: GRAY[500], fontSize: 13 }}>{label}</Text>
            <Text key={`val-${label}`} style={{ color: GRAY[800], fontSize: 13, fontWeight: 500 }}>{value}</Text>
          </>
        ))}
      </div>

      {detail.recoveries.length > 0 && (
        <>
          <Text style={{ fontWeight: 600, color: GRAY[700], fontSize: 14, display: 'block', marginBottom: 12 }}>
            회수 이력
          </Text>
          <Timeline
            items={detail.recoveries.map((r) => ({
              color: COLOR_PRIMARY,
              children: (
                <Space direction="vertical" size={2}>
                  <Text style={{ fontWeight: 600, color: GRAY[700], fontSize: 13 }}>
                    {r.settleMonth} 정산월
                  </Text>
                  <Text style={{ color: GRAY[500], fontSize: 12 }}>
                    회수액: {fmt(r.recoveredAmount)}원
                  </Text>
                  <Text style={{ color: GRAY[400], fontSize: 11 }}>
                    {dayjs(r.createdAt).format('YYYY-MM-DD')}
                  </Text>
                </Space>
              ),
            }))}
          />
        </>
      )}

      {detail.recoveries.length === 0 && (
        <Text style={{ color: GRAY[400], fontSize: 13 }}>회수 이력이 없습니다.</Text>
      )}
    </>
  );
}
