import Link from "next/link";
import { and, asc, desc, eq, inArray, ilike, or } from "drizzle-orm";
import { requireSession } from "@/lib/auth";
import { db } from "@/db";
import { tasks, users, auditLogs } from "@/db/schema";
import { visibleUserIds } from "@/lib/rbac";
import { ROLE_RANK, type Role } from "@/lib/accounts";
import { today, weekStart, weekDays } from "@/lib/period";
import { formatDate, formatDateTime } from "@/lib/format";
import { OPEN_TASK_STATUSES, TASK_STATUSES, TASK_STATUS_LABEL } from "@/lib/tasks";
import { ActionForm } from "@/components/action-form";
import { PageHeader, Badge, EmptyState, SectionTitle } from "@/components/ui";
import { createTaskAction, deleteTaskAction, updateTaskAction, updateTaskStatusAction } from "./actions";

export const dynamic = "force-dynamic";

const TONE: Record<string, "neutral" | "green" | "red" | "gold" | "brand"> = {
  NOT_STARTED: "neutral",
  WAITING: "gold",
  DONE: "green",
  POSTPONED: "gold",
  INCOMPLETE: "red",
  CANCELLED: "neutral",
};

const QUICK = [
  { key: "", label: "Tất cả" },
  { key: "qua-han", label: "Quá hạn" },
  { key: "hom-nay", label: "Hôm nay" },
  { key: "tuan", label: "Tuần này" },
] as const;

export default async function TaskListPage({
  searchParams,
}: {
  searchParams: Promise<{ xem?: string; tt?: string; q?: string; han?: string }>;
}) {
  const session = await requireSession();
  const params = await searchParams;
  const todayIso = today();

  // Cấp trên thấy thêm việc của cấp dưới trong phạm vi mình quản lý (cha thấy con, không có chiều ngược lại).
  const scopeIds = session.role === "SALES" ? [session.userId] : await visibleUserIds(session);
  const canSeeTeam = session.role !== "SALES";
  const view = params.xem === "nhom" && canSeeTeam ? "nhom" : "toi";

  // Giao việc: cha giao cho con — người nhận phải có vai trò thấp hơn và nằm trong nhánh (Ban giám đốc: mọi người).
  const assignable =
    session.role === "SALES"
      ? []
      : (
          await db
            .select({ id: users.id, name: users.fullName, role: users.role })
            .from(users)
            .where(
              and(
                eq(users.tenantId, session.tenantId),
                eq(users.isActive, true),
                scopeIds ? inArray(users.id, scopeIds) : undefined,
              ),
            )
            .orderBy(asc(users.fullName))
        ).filter((u) => u.id === session.userId || session.role === "DIRECTOR" || ROLE_RANK[u.role as Role] < ROLE_RANK[session.role]);

  const mineFilter = or(eq(tasks.assigneeId, session.userId), eq(tasks.createdBy, session.userId));
  const teamFilter = scopeIds ? inArray(tasks.assigneeId, scopeIds) : undefined;
  const search = (params.q ?? "").trim();

  const rows = await db
    .select({
      id: tasks.id,
      title: tasks.title,
      description: tasks.description,
      startDate: tasks.startDate,
      dueDate: tasks.dueDate,
      status: tasks.status,
      reason: tasks.reason,
      assigneeId: tasks.assigneeId,
      createdBy: tasks.createdBy,
      assigneeName: users.fullName,
      updatedAt: tasks.updatedAt,
    })
    .from(tasks)
    .innerJoin(users, eq(tasks.assigneeId, users.id))
    .where(
      and(
        eq(tasks.tenantId, session.tenantId),
        view === "nhom" ? teamFilter : mineFilter,
        search ? or(ilike(tasks.title, `%${search}%`), ilike(tasks.description, `%${search}%`)) : undefined,
      ),
    )
    .orderBy(asc(tasks.startDate), desc(tasks.createdAt))
    .limit(300);

  // Lọc nhanh theo hạn: quá hạn / hôm nay / tuần này (chỉ tính việc còn mở).
  const weekEnd = weekDays(weekStart(todayIso))[6];
  const quick = QUICK.some((q) => q.key === params.han) ? (params.han ?? "") : "";
  const quickFilter = (row: (typeof rows)[number]) => {
    if (!quick) return true;
    if (!OPEN_TASK_STATUSES.includes(row.status)) return false;
    if (quick === "qua-han") return !!row.dueDate && row.dueDate < todayIso;
    if (quick === "hom-nay") return (row.startDate === todayIso) || row.dueDate === todayIso;
    return (row.startDate && row.startDate <= weekEnd && row.startDate >= todayIso) || (row.dueDate && row.dueDate <= weekEnd && row.dueDate >= todayIso);
  };

  const filterStatus = TASK_STATUSES.some((s) => s.key === params.tt) ? params.tt : "";
  const shown = rows.filter((r) => (!filterStatus || r.status === filterStatus) && quickFilter(r));
  const open = shown.filter((r) => OPEN_TASK_STATUSES.includes(r.status));
  const closed = shown.filter((r) => !OPEN_TASK_STATUSES.includes(r.status));

  // Lịch sử đổi trạng thái / nội dung của các việc đang hiển thị (từ nhật ký thao tác), tối đa 4 dòng mỗi việc.
  const history = new Map<string, { at: Date; who: string; text: string }[]>();
  if (shown.length > 0) {
    const logs = await db
      .select({ entityId: auditLogs.entityId, at: auditLogs.createdAt, payload: auditLogs.payload, who: users.fullName, action: auditLogs.action })
      .from(auditLogs)
      .leftJoin(users, eq(auditLogs.userId, users.id))
      .where(
        and(
          eq(auditLogs.tenantId, session.tenantId),
          eq(auditLogs.entityType, "task"),
          inArray(auditLogs.entityId, shown.map((r) => r.id)),
        ),
      )
      .orderBy(desc(auditLogs.createdAt))
      .limit(800);
    for (const log of logs) {
      if (!log.entityId) continue;
      const changes = (log.payload as { changes?: Record<string, { from: unknown; to: unknown }> } | null)?.changes;
      const parts: string[] = [];
      if (changes?.status) parts.push(`${TASK_STATUS_LABEL[String(changes.status.from)] ?? "—"} → ${TASK_STATUS_LABEL[String(changes.status.to)] ?? String(changes.status.to)}`);
      if (changes?.reason?.to) parts.push(`lý do: ${String(changes.reason.to)}`);
      const day = (value: unknown) => (value ? formatDate(String(value)) : "—");
      if (changes?.startDate) parts.push(`bắt đầu ${day(changes.startDate.from)} → ${day(changes.startDate.to)}`);
      if (changes?.dueDate) parts.push(`hạn ${day(changes.dueDate.from)} → ${day(changes.dueDate.to)}`);
      if (changes?.title) parts.push("đổi tên");
      if (changes?.assigneeId) parts.push("đổi người thực hiện");
      const text = log.action === "CREATE" ? "Tạo công việc" : parts.join(" · ");
      if (!text) continue;
      const list = history.get(log.entityId) ?? [];
      if (list.length < 4) list.push({ at: log.at, who: log.who ?? "—", text });
      history.set(log.entityId, list);
    }
  }

  const renderRow = (row: (typeof rows)[number]) => {
    const overdue = OPEN_TASK_STATUSES.includes(row.status) && !!row.dueDate && row.dueDate < todayIso;
    const isCreator = row.createdBy === session.userId;
    const canChangeStatus = row.assigneeId === session.userId || isCreator;
    const logs = history.get(row.id) ?? [];
    return (
      <div key={row.id} className="card p-3.5">
        <div className="flex flex-wrap items-start justify-between gap-2">
          <div className="min-w-0">
            <div className="text-sm font-semibold text-ink-700">{row.title}</div>
            {row.description && <div className="mt-0.5 whitespace-pre-line text-xs text-ink-500">{row.description}</div>}
            <div className="mt-1 text-[11px] text-ink-400">
              {row.startDate ? `Bắt đầu ${formatDate(row.startDate)}` : "Chưa đặt ngày bắt đầu"}
              {row.dueDate ? ` · hạn ${formatDate(row.dueDate)}` : ""}
              {(row.assigneeId !== session.userId || view === "nhom") && ` · người thực hiện: ${row.assigneeName}`}
              {!isCreator && row.assigneeId === session.userId && " · được giao"}
            </div>
            {row.reason && <div className="mt-1 text-xs text-ink-600">Lý do: {row.reason}</div>}
          </div>
          <div className="flex shrink-0 items-center gap-1.5">
            {overdue && <Badge tone="red">Quá hạn</Badge>}
            <Badge tone={TONE[row.status] ?? "neutral"}>{TASK_STATUS_LABEL[row.status] ?? row.status}</Badge>
          </div>
        </div>

        {(canChangeStatus || logs.length > 0) && (
          <details className="mt-2">
            <summary className="cursor-pointer text-xs font-semibold text-brand-600">Cập nhật / chi tiết</summary>

            {canChangeStatus && (
              <ActionForm action={updateTaskStatusAction} success="Đã cập nhật công việc." className="mt-2 flex flex-wrap items-end gap-2">
                <input type="hidden" name="id" value={row.id} />
                <select name="status" defaultValue={row.status} className="input w-auto" aria-label="Trạng thái">
                  {TASK_STATUSES.map((s) => (
                    <option key={s.key} value={s.key}>
                      {s.label}
                    </option>
                  ))}
                </select>
                <input name="reason" defaultValue={row.reason ?? ""} className="input min-w-52 flex-1" placeholder="Lý do (bắt buộc khi dời / huỷ / chưa hoàn thành)" />
                <label className="text-[11px] text-ink-400">
                  Khi dời — bắt đầu mới
                  <input name="newStartDate" type="date" className="input" />
                </label>
                <label className="text-[11px] text-ink-400">
                  Hạn mới
                  <input name="newDueDate" type="date" className="input" />
                </label>
                <button type="submit" className="btn-ghost">
                  Lưu
                </button>
              </ActionForm>
            )}

            {isCreator && (
              <details className="mt-3 rounded-lg border border-[var(--color-line)] p-3">
                <summary className="cursor-pointer text-xs font-semibold text-ink-600">Sửa nội dung công việc</summary>
                <ActionForm action={updateTaskAction} success="Đã cập nhật công việc." className="mt-2 grid gap-2 sm:grid-cols-2">
                  <input type="hidden" name="id" value={row.id} />
                  <input name="title" required defaultValue={row.title} className="input sm:col-span-2" aria-label="Tên công việc" />
                  <textarea name="description" rows={2} defaultValue={row.description ?? ""} className="input sm:col-span-2" aria-label="Ghi chú" />
                  <label className="text-[11px] text-ink-400">
                    Ngày bắt đầu
                    <input name="startDate" type="date" defaultValue={row.startDate ?? ""} className="input" />
                  </label>
                  <label className="text-[11px] text-ink-400">
                    Hạn hoàn thành
                    <input name="dueDate" type="date" defaultValue={row.dueDate ?? ""} className="input" />
                  </label>
                  {assignable.length > 0 && (
                    <label className="text-[11px] text-ink-400 sm:col-span-2">
                      Người thực hiện
                      <select name="assigneeId" defaultValue={row.assigneeId} className="input">
                        {assignable.some((p) => p.id === row.assigneeId) ? null : <option value={row.assigneeId}>{row.assigneeName}</option>}
                        {assignable.map((p) => (
                          <option key={p.id} value={p.id}>
                            {p.id === session.userId ? "Chính tôi" : p.name}
                          </option>
                        ))}
                      </select>
                    </label>
                  )}
                  <button type="submit" className="btn-primary self-start px-3 py-1.5 text-xs">
                    Lưu nội dung
                  </button>
                </ActionForm>
                <ActionForm action={deleteTaskAction} success="Đã xoá công việc." confirm="Xoá công việc này?" className="mt-2">
                  <input type="hidden" name="id" value={row.id} />
                  <button type="submit" className="text-xs text-red-600 hover:underline">
                    Xoá công việc
                  </button>
                </ActionForm>
              </details>
            )}

            {logs.length > 0 && (
              <ul className="mt-3 border-t border-[var(--color-line)] pt-2 text-[11px] text-ink-400">
                {logs.map((log, index) => (
                  <li key={index}>
                    {formatDateTime(log.at)} · {log.who}: {log.text}
                  </li>
                ))}
              </ul>
            )}
          </details>
        )}
      </div>
    );
  };

  const filterLink = (patch: Record<string, string>) => {
    const q = new URLSearchParams();
    const merged: Record<string, string> = { xem: view === "nhom" ? "nhom" : "", tt: filterStatus ?? "", q: search, han: quick, ...patch };
    for (const [k, v] of Object.entries(merged)) if (v) q.set(k, v);
    const qs = q.toString();
    return qs ? `/cong-viec/danh-sach?${qs}` : "/cong-viec/danh-sach";
  };

  return (
    <>
      <PageHeader
        title="Danh sách công việc"
        subtitle="Ghi lại việc cần hoàn thành, ngày bắt đầu và trạng thái. Cấp trên giao được việc cho cấp dưới."
        actions={
          <>
            <Link href="/cong-viec/lich" className="btn-ghost">
              Lịch
            </Link>
            <Link href="/cong-viec" className="btn-ghost">
              ← Công việc theo tuần
            </Link>
          </>
        }
      />

      <div className="card mb-5 p-4">
        <ActionForm action={createTaskAction} success="Đã thêm công việc." resetOnSuccess className="grid gap-3 lg:grid-cols-4">
          <div className="lg:col-span-2">
            <label htmlFor="title" className="label-caps mb-1.5 block">
              Công việc cần làm
            </label>
            <input id="title" name="title" required className="input" placeholder="Gọi lại phòng khám Ánh Dương chốt đơn" />
          </div>
          <div>
            <label htmlFor="startDate" className="label-caps mb-1.5 block">
              Ngày bắt đầu
            </label>
            <input id="startDate" name="startDate" type="date" defaultValue={todayIso} className="input" />
          </div>
          <div>
            <label htmlFor="dueDate" className="label-caps mb-1.5 block">
              Hạn hoàn thành
            </label>
            <input id="dueDate" name="dueDate" type="date" className="input" />
          </div>
          <div className="lg:col-span-2">
            <label htmlFor="description" className="label-caps mb-1.5 block">
              Ghi chú
            </label>
            <input id="description" name="description" className="input" placeholder="Chi tiết cần nhớ…" />
          </div>
          {assignable.length > 1 && (
            <div>
              <label htmlFor="assigneeId" className="label-caps mb-1.5 block">
                Giao cho
              </label>
              <select id="assigneeId" name="assigneeId" defaultValue="" className="input">
                <option value="">Chính tôi</option>
                {assignable
                  .filter((p) => p.id !== session.userId)
                  .map((p) => (
                    <option key={p.id} value={p.id}>
                      {p.name}
                    </option>
                  ))}
              </select>
            </div>
          )}
          <div className="flex items-end">
            <button type="submit" className="btn-primary">
              Thêm công việc
            </button>
          </div>
        </ActionForm>
      </div>

      <div className="mb-2 flex flex-wrap gap-1">
        {QUICK.map((item) => (
          <Link
            key={item.key || "all"}
            href={filterLink({ han: item.key })}
            className={`rounded-md px-3 py-1.5 text-sm font-semibold ${quick === item.key ? "bg-brand-500 text-white" : "border border-[var(--color-line)] bg-white text-ink-500 hover:bg-ink-50"}`}
          >
            {item.label}
          </Link>
        ))}
      </div>

      <form className="mb-4 flex flex-wrap items-end gap-3" action="/cong-viec/danh-sach">
        {quick && <input type="hidden" name="han" value={quick} />}
        <div className="min-w-48 flex-1">
          <label htmlFor="q" className="label-caps mb-1.5 block">
            Tìm công việc
          </label>
          <input id="q" name="q" defaultValue={search} className="input" placeholder="Tên hoặc ghi chú…" />
        </div>
        {canSeeTeam && (
          <div>
            <label htmlFor="xem" className="label-caps mb-1.5 block">
              Xem
            </label>
            <select id="xem" name="xem" defaultValue={view} className="input">
              <option value="toi">Việc của tôi</option>
              <option value="nhom">Việc của nhóm tôi quản lý</option>
            </select>
          </div>
        )}
        <div>
          <label htmlFor="tt" className="label-caps mb-1.5 block">
            Trạng thái
          </label>
          <select id="tt" name="tt" defaultValue={filterStatus} className="input">
            <option value="">Tất cả</option>
            {TASK_STATUSES.map((s) => (
              <option key={s.key} value={s.key}>
                {s.label}
              </option>
            ))}
          </select>
        </div>
        <button type="submit" className="btn-ghost">
          Lọc
        </button>
      </form>

      {shown.length === 0 ? (
        <EmptyState message="Không có công việc nào phù hợp." hint="Thêm việc cần làm ở khung phía trên, hoặc đổi bộ lọc." />
      ) : (
        <div className="flex flex-col gap-5">
          <div>
            <SectionTitle hint={`${open.length} việc`}>Đang làm</SectionTitle>
            <div className="flex flex-col gap-2">{open.length === 0 ? <p className="text-sm text-ink-400">Không có việc nào đang làm.</p> : open.map(renderRow)}</div>
          </div>
          {closed.length > 0 && (
            <div>
              <SectionTitle hint={`${closed.length} việc`}>Đã kết thúc</SectionTitle>
              <div className="flex flex-col gap-2">{closed.map(renderRow)}</div>
            </div>
          )}
        </div>
      )}
    </>
  );
}
