import { groupBy } from 'es-toolkit';
import { TrendingUpIcon } from 'lucide-react';
import {
  Area,
  AreaChart,
  Bar,
  BarChart,
  CartesianGrid,
  PolarAngleAxis,
  PolarGrid,
  Radar,
  RadarChart,
  XAxis,
  YAxis,
} from 'recharts';

import type { Post } from '@/entities/post';
import {
  Card,
  CardContent,
  CardDescription,
  CardFooter,
  CardHeader,
  CardTitle,
} from '@/shared/ui/card';
import {
  ChartContainer,
  ChartTooltip,
  ChartTooltipContent,
  type ChartConfig,
} from '@/shared/ui/chart';

type PostChartsProps = {
  /** 현재 필터(검색·작성자)가 적용된 목록 — 차트도 표와 같은 데이터를 본다. */
  posts: Post[];
};

type AuthorStat = {
  userId: number;
  author: string;
  count: number;
  avgBody: number;
  avgTitle: number;
};

const avgOf = (items: Post[], pick: (post: Post) => number) =>
  Math.round(items.reduce((sum, post) => sum + pick(post), 0) / items.length);

const toAuthorStats = (posts: Post[]): AuthorStat[] => {
  const byAuthor = groupBy(posts, (post) => post.userId);
  return Object.entries(byAuthor)
    .map(([userId, items]) => ({
      userId: Number(userId),
      author: `작성자 ${userId}`,
      count: items.length,
      avgBody: avgOf(items, (post) => post.body.length),
      avgTitle: avgOf(items, (post) => post.title.length),
    }))
    .sort((a, b) => a.userId - b.userId);
};

const toIdBuckets = (posts: Post[]) => {
  return Array.from({ length: 10 }, (_, index) => {
    const start = index * 10 + 1;
    const items = posts.filter(
      (post) => post.id >= start && post.id <= start + 9
    );
    return {
      range: `${start}~${start + 9}`,
      avgBody:
        items.length === 0 ? 0 : avgOf(items, (post) => post.body.length),
    };
  });
};

const bodyConfig = {
  avgBody: { label: '평균 본문 길이', color: 'var(--chart-1)' },
} satisfies ChartConfig;

const titleConfig = {
  avgTitle: { label: '평균 제목 길이', color: 'var(--chart-2)' },
} satisfies ChartConfig;

export const PostCharts = ({ posts }: PostChartsProps) => {
  const stats = toAuthorStats(posts);

  return (
    <div className="space-y-3">
      <BodyByRangeCard posts={posts} />
      <div className="grid gap-3 lg:grid-cols-2">
        <TitleByAuthorCard stats={stats} />
        <BodyByAuthorCard stats={stats} />
      </div>
    </div>
  );
};

const BodyByRangeCard = ({ posts }: { posts: Post[] }) => {
  const buckets = toIdBuckets(posts);
  const longest = buckets.reduce((a, b) => (b.avgBody > a.avgBody ? b : a));

  return (
    <Card>
      <CardHeader>
        <CardTitle>글 번호 구간별 평균 본문 길이</CardTitle>
        <CardDescription>
          지금 걸린 검색·필터 기준이에요. 글자 수로 계산해요.
        </CardDescription>
      </CardHeader>
      <CardContent>
        <ChartContainer config={bodyConfig} className="h-64 w-full">
          <AreaChart accessibilityLayer data={buckets}>
            <defs>
              <linearGradient id="fillBody" x1="0" y1="0" x2="0" y2="1">
                <stop
                  offset="5%"
                  stopColor="var(--color-avgBody)"
                  stopOpacity={0.35}
                />
                <stop
                  offset="95%"
                  stopColor="var(--color-avgBody)"
                  stopOpacity={0.02}
                />
              </linearGradient>
            </defs>
            <CartesianGrid vertical={false} />
            <XAxis
              dataKey="range"
              tickLine={false}
              axisLine={false}
              tickMargin={8}
            />
            <YAxis hide domain={['dataMin - 30', 'dataMax + 15']} />
            <ChartTooltip content={<ChartTooltipContent />} />
            <Area
              dataKey="avgBody"
              type="natural"
              fill="url(#fillBody)"
              stroke="var(--color-avgBody)"
              strokeWidth={2}
            />
          </AreaChart>
        </ChartContainer>
      </CardContent>
      <CardFooter className="gap-2 text-sm text-muted-foreground">
        <TrendingUpIcon aria-hidden className="size-4" />
        본문이 가장 긴 구간은 {longest.range}번이에요 (평균 {longest.avgBody}자)
      </CardFooter>
    </Card>
  );
};

const TitleByAuthorCard = ({ stats }: { stats: AuthorStat[] }) => {
  const longest = stats.reduce((a, b) => (b.avgTitle > a.avgTitle ? b : a));

  return (
    <Card>
      <CardHeader>
        <CardTitle>작성자별 평균 제목 길이</CardTitle>
        <CardDescription>제목을 길게 쓰는 사람이 보여요.</CardDescription>
      </CardHeader>
      <CardContent>
        <ChartContainer config={titleConfig} className="h-56 w-full">
          <BarChart accessibilityLayer data={stats}>
            <CartesianGrid vertical={false} />
            <XAxis
              dataKey="author"
              tickLine={false}
              axisLine={false}
              tickMargin={8}
              tickFormatter={(value: string) => value.replace('작성자 ', '')}
            />
            <YAxis hide domain={[0, 'dataMax + 10']} />
            <ChartTooltip content={<ChartTooltipContent />} />
            <Bar dataKey="avgTitle" fill="var(--color-avgTitle)" radius={6} />
          </BarChart>
        </ChartContainer>
      </CardContent>
      <CardFooter className="gap-2 text-sm text-muted-foreground">
        <TrendingUpIcon aria-hidden className="size-4" />
        제목이 가장 긴 사람은 {longest.author}예요 (평균 {longest.avgTitle}자)
      </CardFooter>
    </Card>
  );
};

const BodyByAuthorCard = ({ stats }: { stats: AuthorStat[] }) => {
  const longest = stats.reduce((a, b) => (b.avgBody > a.avgBody ? b : a));

  return (
    <Card>
      <CardHeader>
        <CardTitle>작성자별 평균 본문 길이</CardTitle>
        <CardDescription>작성자 사이의 균형을 한눈에 봐요.</CardDescription>
      </CardHeader>
      <CardContent>
        <ChartContainer config={bodyConfig} className="h-56 w-full">
          <RadarChart accessibilityLayer data={stats}>
            <PolarGrid />
            <PolarAngleAxis
              dataKey="author"
              tickFormatter={(value: string) => value.replace('작성자 ', '')}
            />
            <ChartTooltip content={<ChartTooltipContent />} />
            <Radar
              dataKey="avgBody"
              fill="var(--color-avgBody)"
              fillOpacity={0.25}
              stroke="var(--color-avgBody)"
              strokeWidth={2}
            />
          </RadarChart>
        </ChartContainer>
      </CardContent>
      <CardFooter className="gap-2 text-sm text-muted-foreground">
        <TrendingUpIcon aria-hidden className="size-4" />
        본문이 가장 긴 사람은 {longest.author}예요 (평균 {longest.avgBody}자)
      </CardFooter>
    </Card>
  );
};
