/**
 * Lịch làm việc cá nhân (yêu cầu mục 4 "Kế hoạch công việc — note lịch công việc để ghi nhớ").
 *
 * Gom vào một dòng thời gian mọi thứ có ngày của người dùng: việc cần làm (ngày bắt đầu và hạn), lộ trình đi tuyến trong
 * kế hoạch tuần, sự kiện chung do người có quyền đăng thông báo và các sự kiện mời khách (ngày diễn ra, hạn chót mời).
 * Không có bảng lịch riêng — ghi chú nhớ việc chính là một công việc có ngày bắt đầu, nên dùng chung danh sách công việc.
 */
import "server-only";
import { and, eq, gte, lte } from "drizzle-orm";
import { db } from "@/db";
import { tasks, planItems, weeklyPlans, inviteEvents } from "@/db/schema";
import type { SessionUser } from "./auth";
import { visibleAnnouncements } from "./announcements";
import { OPEN_TASK_STATUSES, TASK_STATUS_LABEL } from "./tasks";
import { today } from "./period";

export type AgendaKind = "task" | "due" | "plan" | "event" | "invite" | "deadline";

export type AgendaItem = {
  id: string;
  date: string;
  kind: AgendaKind;
  title: string;
  sub?: string;
  href: string;
  /** Đã xong / kết thúc — hiển thị mờ. */
  closed: boolean;
  /** Việc còn mở mà đã quá hạn. */
  overdue: boolean;
};

export const AGENDA_KIND_LABEL: Record<AgendaKind, string> = {
  task: "Việc",
  due: "Hạn",
  plan: "Lộ trình",
  event: "Sự kiện",
  invite: "Sự kiện mời khách",
  deadline: "Hạn chót mời khách",
};

export async function agendaFor(session: SessionUser, from: string, to: string): Promise<AgendaItem[]> {
  const todayIso = today();
  const items: AgendaItem[] = [];

  const [taskRows, planRows, news, inviteRows] = await Promise.all([
    db
      .select({
        id: tasks.id,
        title: tasks.title,
        status: tasks.status,
        startDate: tasks.startDate,
        dueDate: tasks.dueDate,
      })
      .from(tasks)
      .where(and(eq(tasks.tenantId, session.tenantId), eq(tasks.assigneeId, session.userId))),
    db
      .select({
        id: planItems.id,
        date: planItems.planDate,
        content: planItems.content,
        timeSlot: planItems.timeSlot,
        status: planItems.status,
      })
      .from(planItems)
      .innerJoin(weeklyPlans, eq(planItems.planId, weeklyPlans.id))
      .where(
        and(
          eq(planItems.tenantId, session.tenantId),
          eq(weeklyPlans.userId, session.userId),
          gte(planItems.planDate, from),
          lte(planItems.planDate, to),
        ),
      ),
    visibleAnnouncements(session, { includeExpired: true }),
    db
      .select({ id: inviteEvents.id, name: inviteEvents.name, eventDate: inviteEvents.eventDate, inviteDeadline: inviteEvents.inviteDeadline })
      .from(inviteEvents)
      .where(eq(inviteEvents.tenantId, session.tenantId)),
  ]);

  const inRange = (d: string | null): d is string => !!d && d >= from && d <= to;

  for (const t of taskRows) {
    const open = OPEN_TASK_STATUSES.includes(t.status);
    const overdue = open && !!t.dueDate && t.dueDate < todayIso;
    const sub = TASK_STATUS_LABEL[t.status];
    if (inRange(t.startDate)) {
      items.push({ id: `t-${t.id}`, date: t.startDate, kind: "task", title: t.title, sub, href: "/cong-viec/danh-sach", closed: !open, overdue });
    }
    if (inRange(t.dueDate) && t.dueDate !== t.startDate) {
      items.push({ id: `d-${t.id}`, date: t.dueDate, kind: "due", title: t.title, sub, href: "/cong-viec/danh-sach", closed: !open, overdue });
    }
  }
  for (const p of planRows) {
    items.push({
      id: `p-${p.id}`,
      date: p.date,
      kind: "plan",
      title: p.content,
      sub: p.timeSlot ?? undefined,
      href: "/cong-viec",
      closed: p.status !== "PLANNED",
      overdue: false,
    });
  }
  for (const a of news) {
    if (inRange(a.eventDate)) {
      items.push({ id: `a-${a.id}`, date: a.eventDate, kind: "event", title: a.title, href: "/", closed: a.eventDate < todayIso, overdue: false });
    }
  }
  for (const e of inviteRows) {
    const href = `/danh-muc/su-kien-moi-khach/${e.id}`;
    if (inRange(e.eventDate)) items.push({ id: `i-${e.id}`, date: e.eventDate, kind: "invite", title: e.name, href, closed: e.eventDate < todayIso, overdue: false });
    if (e.inviteDeadline && e.inviteDeadline !== e.eventDate && inRange(e.inviteDeadline)) {
      items.push({ id: `l-${e.id}`, date: e.inviteDeadline, kind: "deadline", title: e.name, href, closed: e.inviteDeadline < todayIso, overdue: false });
    }
  }

  return items.sort((a, b) => a.date.localeCompare(b.date) || Number(a.closed) - Number(b.closed));
}
