import { NextResponse } from "next/server";
import { PrismaClient } from "@prisma/client";
import { verifyAccessToken } from "@/features/auth/authCrypto";

// 대시보드 개요 API (/api/dashboard/overview)
// - 로그인한 사용자의 프로젝트/폼 제출 통계를 집계해 요약/프로젝트별 지표를 반환한다.
// - DB 스키마: Project, FormSubmission
// - 인증: pb_access 쿠키(JWT)를 검증해 현재 사용자 식별

const prisma = new PrismaClient();

interface AuthUser {
  id: string;
  email: string;
  tokenVersion: number;
}

// 공통: pb_access 쿠키에서 JWT 토큰을 추출한다.
function extractTokenFromCookieHeader(cookieHeader: string | null): string | null {
  if (!cookieHeader) return null;

  const parts = cookieHeader.split(";");
  for (const part of parts) {
    const trimmed = part.trim();
    if (trimmed.startsWith("pb_access=")) {
      const value = trimmed.substring("pb_access=".length);
      return decodeURIComponent(value);
    }
  }
  return null;
}

// 공통: Request 헤더의 쿠키에서 인증된 유저 정보를 복원한다.
async function getAuthUserFromRequest(request: Request): Promise<AuthUser | null> {
  const cookieHeader = request.headers.get("cookie");
  const token = extractTokenFromCookieHeader(cookieHeader);
  if (!token) return null;

  const payload = await verifyAccessToken(token);
  if (!payload) return null;

  return {
    id: payload.sub,
    email: payload.email,
    tokenVersion: payload.tokenVersion,
  };
}

interface SummaryStats {
  totalProjects: number;
  totalSubmissions: number;
  todaySubmissions: number;
  last7DaysSubmissions: number;
}

interface DailySubmissionItem {
  // 일별 제출 수 그래프를 위한 집계 데이터
  date: string; // YYYY-MM-DD (UTC 기준)
  count: number;
}

interface ProjectStatsItem {
  projectId: string;
  title: string;
  slug: string;
  status: string;
  totalSubmissions: number;
  lastSubmissionAt: string | null;
}

// GET /api/dashboard/overview
// - 현재 로그인 사용자의 프로젝트 목록/폼 제출 내역을 조회해 통계를 계산한다.
export async function GET(request: Request) {
  const authUser = await getAuthUserFromRequest(request);
  if (!authUser) {
    return NextResponse.json(
      { message: "대시보드를 조회하려면 로그인이 필요합니다." },
      { status: 401 },
    );
  }

  try {
    // 현재 사용자 소유 프로젝트와, 해당 사용자가 소유한 제출 내역을 한 번에 로드한다.
    const [projects, submissions] = await Promise.all([
      prisma.project.findMany({
        where: { userId: authUser.id },
        select: {
          id: true,
          title: true,
          slug: true,
          status: true,
        },
      }),
      prisma.formSubmission.findMany({
        where: { userId: authUser.id },
        select: {
          id: true,
          projectId: true,
          projectSlug: true,
          createdAt: true,
        },
      }),
    ]);

    const totalProjects = projects.length;
    const totalSubmissions = submissions.length;

    // 오늘/최근 7일 기준 시각 계산
    const now = new Date();
    const startOfToday = new Date(now);
    startOfToday.setHours(0, 0, 0, 0);
    const sevenDaysAgo = new Date(now.getTime() - 7 * 24 * 60 * 60 * 1000);

    let todaySubmissions = 0;
    let last7DaysSubmissions = 0;

    for (const submission of submissions) {
      const createdAt = submission.createdAt instanceof Date
        ? submission.createdAt
        : new Date(submission.createdAt as unknown as string);

      if (createdAt >= startOfToday) {
        todaySubmissions += 1;
      }

      if (createdAt >= sevenDaysAgo) {
        last7DaysSubmissions += 1;
      }
    }

    // 프로젝트별 통계 맵을 구성한다.
    const statsByProjectId = new Map<
      string,
      {
        projectId: string;
        title: string;
        slug: string;
        status: string;
        totalSubmissions: number;
        lastSubmissionAt: Date | null;
      }
    >();

    for (const project of projects) {
      statsByProjectId.set(project.id, {
        projectId: project.id,
        title: project.title,
        slug: project.slug,
        status: project.status,
        totalSubmissions: 0,
        lastSubmissionAt: null,
      });
    }

    for (const submission of submissions) {
      const stat = submission.projectId ? statsByProjectId.get(submission.projectId) : null;
      if (!stat) continue;

      stat.totalSubmissions += 1;

      const createdAt = submission.createdAt instanceof Date
        ? submission.createdAt
        : new Date(submission.createdAt as unknown as string);

      if (!stat.lastSubmissionAt || createdAt > stat.lastSubmissionAt) {
        stat.lastSubmissionAt = createdAt;
      }
    }

    const projectStats: ProjectStatsItem[] = Array.from(statsByProjectId.values()).map((item) => ({
      projectId: item.projectId,
      title: item.title,
      slug: item.slug,
      status: item.status,
      totalSubmissions: item.totalSubmissions,
      lastSubmissionAt: item.lastSubmissionAt ? item.lastSubmissionAt.toISOString() : null,
    }));

    const summaryStats: SummaryStats = {
      totalProjects,
      totalSubmissions,
      todaySubmissions,
      last7DaysSubmissions,
    };

    // 일별 전체 제출 수를 집계해 그래프용 데이터로 변환한다.
    const countsByDate = new Map<string, number>();

    for (const submission of submissions) {
      const createdAt = submission.createdAt instanceof Date
        ? submission.createdAt
        : new Date(submission.createdAt as unknown as string);

      const dateKey = createdAt.toISOString().slice(0, 10); // YYYY-MM-DD
      const prev = countsByDate.get(dateKey) ?? 0;
      countsByDate.set(dateKey, prev + 1);
    }

    const dailySubmissions: DailySubmissionItem[] = Array.from(countsByDate.entries())
      .map(([date, count]) => ({ date, count }))
      .sort((a, b) => a.date.localeCompare(b.date));

    return NextResponse.json(
      {
        summaryStats,
        projectStats,
        dailySubmissions,
      },
      { status: 200 },
    );
  } catch (error: any) {
    return NextResponse.json(
      {
        message: "대시보드 데이터를 계산하는 중 오류가 발생했습니다.",
        error: error?.message,
      },
      { status: 500 },
    );
  }
}
