import { useMemo, useState } from 'react';
import { Alert, Col, Row, Typography } from 'antd';
import { ProCard } from '@ant-design/pro-components';
import { useQuery } from '@tanstack/react-query';
import {
  LineChart, Line, XAxis, YAxis, CartesianGrid,
  Tooltip, ResponsiveContainer, Legend,
} from 'recharts';
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 { kpiApi, RetentionRow, KpiSearchParam } from '@/api/kpi';
import {
  COLOR_PRIMARY, COLOR_SUCCESS, GRAY, SHADOW, RADIUS,
} from '@/theme/tokens';

const { Text } = Typography;

const fmtPct = (v: number) => `${v.toFixed(1)}%`;

// AG Grid 컬럼
const COLUMNS: ColDef<RetentionRow>[] = [
  { field: 'contractMonth',    headerName: '계약 기준월', width: 130, pinned: 'left' },
  { field: 'carrierName',      headerName: '보험사',      width: 140 },
  { field: 'totalContracts',   headerName: '전체 계약',   width: 110, type: 'numericColumn', valueFormatter: (p) => (p.value ?? 0).toLocaleString() },
  { field: 'retained13m',      headerName: '13M 유지건',  flex: 1,    type: 'numericColumn', valueFormatter: (p) => (p.value ?? 0).toLocaleString() },
  { field: 'retained25m',      headerName: '25M 유지건',  flex: 1,    type: 'numericColumn', valueFormatter: (p) => (p.value ?? 0).toLocaleString() },
  {
    field: 'retentionRate13m', headerName: '13M 유지율%', flex: 1, type: 'numericColumn',
    valueFormatter: (p) => fmtPct(p.value ?? 0),
    cellStyle: (p) => ({ color: (p.value ?? 0) >= 80 ? COLOR_SUCCESS : (p.value ?? 0) >= 60 ? '#F59E0B' : '#F04452' }),
  },
  {
    field: 'retentionRate25m', headerName: '25M 유지율%', flex: 1, type: 'numericColumn',
    valueFormatter: (p) => fmtPct(p.value ?? 0),
    cellStyle: (p) => ({ color: (p.value ?? 0) >= 70 ? COLOR_SUCCESS : (p.value ?? 0) >= 50 ? '#F59E0B' : '#F04452' }),
  },
];

// ────────────────────────────────────────────────────────
// 상단 카드
// ────────────────────────────────────────────────────────

interface AvgCardProps { label: string; value: number; color: string; bg: string }

function AvgCard({ label, value, color, bg }: AvgCardProps) {
  return (
    <div style={{
      background: '#ffffff',
      borderRadius: RADIUS.lg,
      border: `1px solid ${GRAY[100]}`,
      boxShadow: SHADOW.sm,
      padding: '24px 28px',
      display: 'flex', flexDirection: 'column', gap: 12,
    }}>
      <Text style={{ fontSize: 13, fontWeight: 500, color: GRAY[500] }}>{label}</Text>
      <div style={{ display: 'flex', alignItems: 'baseline', gap: 6 }}>
        <span style={{
          fontSize: 34, fontWeight: 700, color: GRAY[800], lineHeight: 1,
          fontFeatureSettings: "'tnum'",
        }}>
          {value.toFixed(1)}
        </span>
        <Text style={{ fontSize: 14, color: GRAY[500] }}>%</Text>
      </div>
      <div style={{
        height: 4, background: GRAY[100], borderRadius: 999, overflow: 'hidden', marginTop: 4,
      }}>
        <div style={{
          height: '100%', width: `${Math.min(value, 100)}%`,
          background: color, backgroundColor: bg,
          borderRadius: 999,
          backgroundImage: `linear-gradient(90deg, ${color}88, ${color})`,
        }} />
      </div>
    </div>
  );
}

// ────────────────────────────────────────────────────────
// 메인
// ────────────────────────────────────────────────────────

export default function KpiRetention() {
  const [params, setParams] = useState<KpiSearchParam>({
    fromMonth: dayjs().subtract(11, 'month').format('YYYYMM'),
    toMonth: dayjs().format('YYYYMM'),
    pageSize: 200,
  });

  const { data, isLoading, isError } = useQuery({
    queryKey: ['kpi', 'retention', params],
    queryFn: () => kpiApi.retention(params),
    retry: false,
  });

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

  // 평균 유지율
  const avg13m = rows.length > 0
    ? rows.reduce((s, r) => s + r.retentionRate13m, 0) / rows.length
    : 0;
  const avg25m = rows.length > 0
    ? rows.reduce((s, r) => s + r.retentionRate25m, 0) / rows.length
    : 0;

  // 차트 — 월별 평균 유지율 (보험사 합산 후 평균)
  const chartData = useMemo(() => {
    const byMonth: Record<string, { sum13: number; sum25: number; cnt: number }> = {};
    for (const r of rows) {
      if (!byMonth[r.contractMonth]) byMonth[r.contractMonth] = { sum13: 0, sum25: 0, cnt: 0 };
      byMonth[r.contractMonth].sum13 += r.retentionRate13m;
      byMonth[r.contractMonth].sum25 += r.retentionRate25m;
      byMonth[r.contractMonth].cnt   += 1;
    }
    return Object.entries(byMonth)
      .sort(([a], [b]) => a.localeCompare(b))
      .slice(-12)
      .map(([month, v]) => ({
        month: month.slice(4, 6) + '월',
        '13M유지율': Math.round((v.sum13 / v.cnt) * 10) / 10,
        '25M유지율': Math.round((v.sum25 / v.cnt) * 10) / 10,
      }));
  }, [rows]);

  // 합계행 (건수 합, 비율은 평균)
  const pinnedRow = rows.length > 0 ? {
    contractMonth: '집계',
    totalContracts: rows.reduce((s, r) => s + r.totalContracts, 0),
    retained13m: rows.reduce((s, r) => s + r.retained13m, 0),
    retained25m: rows.reduce((s, r) => s + r.retained25m, 0),
    retentionRate13m: avg13m,
    retentionRate25m: avg25m,
  } as Partial<RetentionRow> : undefined;

  const handleSearch = (values: Record<string, unknown>) => {
    setParams({
      fromMonth: values.fromMonth as string | undefined,
      toMonth: values.toMonth as string | undefined,
      pageSize: 200,
    });
  };

  return (
    <PageContainer
      title="유지율 현황"
      description="13개월 / 25개월 계약 유지율 — Materialized View"
    >
      <SearchForm
        conditions={[
          { type: 'month', name: 'fromMonth', label: '시작 월', span: 6 },
          { type: 'month', name: 'toMonth',   label: '종료 월', span: 6 },
        ]}
        onSearch={handleSearch}
        onReset={() => setParams({
          fromMonth: dayjs().subtract(11, 'month').format('YYYYMM'),
          toMonth: dayjs().format('YYYYMM'),
          pageSize: 200,
        })}
      />

      {isError && (
        <Alert type="warning" showIcon
          message="API 미응답"
          description="/api/kpi/retention 를 확인하세요."
          style={{ marginBottom: 16 }}
        />
      )}

      {/* 카드 2개 */}
      <Row gutter={20} style={{ marginBottom: 20 }}>
        <Col span={12}>
          <AvgCard label="평균 13M 유지율" value={avg13m} color={COLOR_PRIMARY} bg={COLOR_PRIMARY} />
        </Col>
        <Col span={12}>
          <AvgCard label="평균 25M 유지율" value={avg25m} color={COLOR_SUCCESS} bg={COLOR_SUCCESS} />
        </Col>
      </Row>

      {/* LineChart */}
      <ProCard
        title={<span style={{ fontSize: 15, fontWeight: 700, color: GRAY[800] }}>월별 유지율 추이</span>}
        subTitle={<span style={{ fontSize: 13, color: GRAY[400] }}>최근 12개월 평균</span>}
        headerBordered
        style={{
          background: '#ffffff', borderRadius: RADIUS.lg,
          border: `1px solid ${GRAY[100]}`, boxShadow: SHADOW.sm,
          marginBottom: 20,
        }}
      >
        <ResponsiveContainer width="100%" height={260}>
          <LineChart data={chartData} margin={{ top: 8, right: 24, left: -8, bottom: 0 }}>
            <CartesianGrid strokeDasharray="3 3" stroke={GRAY[100]} vertical={false} />
            <XAxis dataKey="month" tick={{ fontSize: 12, fill: GRAY[500] }} axisLine={false} tickLine={false} />
            <YAxis
              tick={{ fontSize: 12, fill: GRAY[500] }} axisLine={false} tickLine={false}
              tickFormatter={(v) => `${v}%`} domain={[0, 100]}
            />
            <Tooltip
              contentStyle={{ borderRadius: 12, border: `1px solid ${GRAY[100]}`, boxShadow: SHADOW.md, fontSize: 13 }}
              formatter={(v: number) => [`${v}%`, '']}
            />
            <Legend wrapperStyle={{ fontSize: 12, paddingTop: 8 }} />
            <Line
              type="monotone" dataKey="13M유지율"
              stroke={COLOR_PRIMARY} strokeWidth={2.5}
              dot={{ fill: COLOR_PRIMARY, r: 3.5 }} activeDot={{ r: 6 }}
            />
            <Line
              type="monotone" dataKey="25M유지율"
              stroke={COLOR_SUCCESS} strokeWidth={2.5}
              dot={{ fill: COLOR_SUCCESS, r: 3.5 }} activeDot={{ r: 6 }}
            />
          </LineChart>
        </ResponsiveContainer>
      </ProCard>

      {/* AG Grid */}
      <ProCard
        style={{
          background: '#ffffff', borderRadius: RADIUS.lg,
          border: `1px solid ${GRAY[100]}`, boxShadow: SHADOW.sm,
        }}
      >
        <DataGrid<RetentionRow>
          rows={rows}
          columns={COLUMNS}
          loading={isLoading}
          height={480}
          pinnedBottomRow={pinnedRow}
        />
      </ProCard>
    </PageContainer>
  );
}
