import { and, asc, eq, gte, lte, desc, sql, inArray } from "drizzle-orm";
import { requireSession } from "@/lib/auth";
import { db } from "@/db";
import {
  weeklyPlans,
  planItems,
  dailyReports,
  checkIns,
  customers,
  users,
  customKpis,
  customKpiEntries,
  customKpiLogs,
} from "@/db/schema";
import { weekStart, weekDays, today, monthKey, monthsInPeriod, quarterOfMonth, monthProgress } from "@/lib/period";
import { formatDate, formatDateTime, formatPeriod } from "@/lib/format";
import { PageHeader, Badge, SectionTitle, TableWrap, EmptyState, ProgressBar } from "@/components/ui";
import { ActionForm } from "@/components/action-form";
import { logKpiProgressAction } from "../danh-muc/kpi-tu-tao/actions";
import { canViewAllStaff, scopeFilter, visibleUserIds } from "@/lib/rbac";
import { buildWeeklySummary } from "@/lib/weekly";
import { WeeklySummaryView } from "@/components/weekly-summary";
import { AddPlanItemForm } from "./add-plan-item-form";
import Link from "next/link";
import { vnDate } from "@/lib/sql-dates";
import { canManageEvents } from "@/lib/events-scope";

export const dynamic = "force-dynamic";

const DAY_LABEL = ["Thứ Hai", "Thứ Ba", "Thứ Tư", "Thứ Năm", "Thứ Sáu", "Thứ Bảy", "Chủ nhật"];

export default async function WorkPage({
  searchParams,
}: {
  searchParams: Promise<{ tuan?: string; nv?: string }>;
}) {
  const session = await requireSession();
  const params = await searchParams;
  const monday = params.tuan ? weekStart(params.tuan) : weekStart(today());
  const days = weekDays(monday);

  // Cha chỉ thấy kế hoạch của con: danh sách chọn nhân viên và tham số ?nv= đều bị giới hạn trong nhánh mình phụ trách.
  const visibleIds = canViewAllStaff(session) ? await visibleUserIds(session) : [];
  const staff = canViewAllStaff(session)
    ? await db
        .select({ id: users.id, fullName: users.fullName })
        .from(users)
        .where(
          and(
            eq(users.tenantId, session.tenantId),
            eq(users.isActive, true),
            eq(users.role, "SALES"),
            visibleIds ? inArray(users.id, visibleIds.length > 0 ? visibleIds : ["00000000-0000-0000-0000-000000000000"]) : undefined,
          ),
        )
        .orderBy(users.fullName)
    : [];

  /* Quản lý xem được kế hoạch của nhân viên; NVKD chỉ xem của mình.
     Ban giám đốc không đi tuyến nên không có kế hoạch riêng — mặc định mở kế hoạch
     của NVKD đầu tiên, thay vì hiện màn hình trống. */
  const requestedId = params.nv && staff.some((person) => person.id === params.nv) ? params.nv : undefined;
  const targetUserId = canViewAllStaff(session)
    ? (requestedId ?? staff[0]?.id ?? session.userId)
    : session.userId;

  // Chỉ NVKD xem lộ trình của chính mình mới thêm được việc mới — quản lý xem
  // lộ trình người khác thì không cần danh sách này.
  const isOwnPlan = targetUserId === session.userId;
  let myCustomers: { id: string; orgName: string; code: string }[] = [];
  if (isOwnPlan) {
    const scope = await scopeFilter(session, {
      tenantId: customers.tenantId,
      ownerId: customers.ownerId,
      territoryId: customers.territoryId,
    });
    myCustomers = await db
      .select({ id: customers.id, orgName: customers.orgName, code: customers.code })
      .from(customers)
      .where(and(scope, eq(customers.isActive, true)))
      .orderBy(asc(customers.orgName));
  }

  const [plan] = await db
    .select()
    .from(weeklyPlans)
    .where(
      and(
        eq(weeklyPlans.tenantId, session.tenantId),
        eq(weeklyPlans.userId, targetUserId),
        eq(weeklyPlans.weekStart, monday),
      ),
    )
    .limit(1);

  const items = plan
    ? await db
        .select({
          id: planItems.id,
          planDate: planItems.planDate,
          content: planItems.content,
          objective: planItems.objective,
          timeSlot: planItems.timeSlot,
          status: planItems.status,
          customerName: customers.orgName,
          customerCode: customers.code,
        })
        .from(planItems)
        .leftJoin(customers, eq(planItems.customerId, customers.id))
        .where(eq(planItems.planId, plan.id))
        .orderBy(planItems.planDate, planItems.sortOrder)
    : [];

  const reports = await db
    .select()
    .from(dailyReports)
    .where(
      and(
        eq(dailyReports.tenantId, session.tenantId),
        eq(dailyReports.userId, targetUserId),
        gte(dailyReports.reportDate, days[0]),
        lte(dailyReports.reportDate, days[6]),
      ),
    )
    .orderBy(desc(dailyReports.reportDate));

  const visits = await db
    .select({
      id: checkIns.id,
      checkedAt: checkIns.checkedAt,
      customerName: customers.orgName,
      distanceMeters: checkIns.distanceMeters,
      outOfRange: checkIns.outOfRange,
      photoPath: checkIns.photoPath,
      note: checkIns.note,
    })
    .from(checkIns)
    .leftJoin(customers, eq(checkIns.customerId, customers.id))
    .where(
      and(
        eq(checkIns.tenantId, session.tenantId),
        eq(checkIns.userId, targetUserId),
        gte(vnDate(checkIns.checkedAt), days[0]),
        lte(vnDate(checkIns.checkedAt), days[6]),
      ),
    )
    .orderBy(desc(checkIns.checkedAt));

  const weekSummary = await buildWeeklySummary(session.tenantId, targetUserId, monday);

  // KPI tự tạo giao cho người đang xem — quy về tháng vì chỉ tiêu tự tạo chỉ
  // theo kỳ tháng, không có kỳ tuần riêng.
  const customKpiRows = await db
    .select({
      id: customKpiEntries.id,
      kpiId: customKpiEntries.kpiId,
      name: customKpis.name,
      unit: customKpis.unit,
      targetValue: customKpiEntries.targetValue,
      actualValue: customKpiEntries.actualValue,
    })
    .from(customKpiEntries)
    .innerJoin(customKpis, eq(customKpiEntries.kpiId, customKpis.id))
    .where(
      and(
        eq(customKpiEntries.tenantId, session.tenantId),
        eq(customKpiEntries.userId, targetUserId),
        eq(customKpiEntries.periodKey, monthKey(today())),
      ),
    )
    .orderBy(asc(customKpis.name));

  /* Cộng dồn KPI tự tạo theo quý và năm: chỉ tiêu giao theo tháng nên quý/năm là tổng các tháng;
     "tuần này" và "hôm nay" lấy từ nhật ký ghi nhận hằng ngày. */
  const yearKey = today().slice(0, 4);
  const monthClock = monthProgress(monthKey(today()));
  const timePct = monthClock.total > 0 ? (monthClock.elapsed / monthClock.total) * 100 : 0;
  const quarterMonths = new Set(monthsInPeriod(quarterOfMonth(monthKey(today()))));
  const yearEntries = await db
    .select({
      kpiId: customKpiEntries.kpiId,
      periodKey: customKpiEntries.periodKey,
      targetValue: customKpiEntries.targetValue,
      actualValue: customKpiEntries.actualValue,
    })
    .from(customKpiEntries)
    .where(
      and(
        eq(customKpiEntries.tenantId, session.tenantId),
        eq(customKpiEntries.userId, targetUserId),
        sql`${customKpiEntries.periodKey} like ${`${yearKey}-%`}`,
      ),
    );
  const kpiLogRows = await db
    .select({ entryId: customKpiLogs.entryId, logDate: customKpiLogs.logDate, value: customKpiLogs.value, note: customKpiLogs.note })
    .from(customKpiLogs)
    .where(
      and(
        eq(customKpiLogs.tenantId, session.tenantId),
        eq(customKpiLogs.userId, targetUserId),
        gte(customKpiLogs.logDate, days[0]),
        lte(customKpiLogs.logDate, days[6]),
      ),
    )
    .orderBy(desc(customKpiLogs.logDate), desc(customKpiLogs.createdAt));

  // Số liệu tổng hợp của tuần do `buildWeeklySummary` tính và `WeeklySummaryView`
  // hiển thị. Trang này từng tự tính lại một bộ song song — bỏ đi để chỉ còn một
  // nguồn duy nhất, tránh hai chỗ ra hai con số khác nhau.

  return (
    <>
      <PageHeader
        title="Công việc theo tuần"
        subtitle={`Tuần ${formatDate(days[0])} – ${formatDate(days[6])}`}
        actions={
          <div className="flex flex-wrap items-end gap-2">
            <form action="/cong-viec" className="flex flex-wrap items-end gap-2">
              {staff.length > 0 && (
                <select name="nv" defaultValue={targetUserId} className="input" aria-label="Chọn nhân viên">
                  {staff.map((person) => (
                    <option key={person.id} value={person.id}>
                      {person.fullName}
                    </option>
                  ))}
                </select>
              )}
              <input type="date" name="tuan" defaultValue={monday} className="input" aria-label="Chọn tuần" />
              <button type="submit" className="btn-ghost">
                Xem
              </button>
            </form>
            <Link href="/cong-viec/lich" className="btn-ghost">
              Lịch
            </Link>
            <Link href="/cong-viec/danh-sach" className="btn-ghost">
              Danh sách công việc
            </Link>
            <Link href="/cong-viec/de-xuat" className="btn-ghost">
              Đề xuất
            </Link>
            <Link href="/danh-muc/su-kien-moi-khach" className="btn-ghost">
              Mời khách sự kiện
            </Link>
            {/* Nhân viên chuyên môn tự ghi lớp đã dạy của mình (quản lý vào từ Danh mục). */}
            {session.role === "SALES" && (await canManageEvents(session)) && (
              <Link href="/danh-muc/su-kien" className="btn-ghost">
                Ghi lớp chuyển giao
              </Link>
            )}
          </div>
        }
      />

      {/* Tổng kết tuần — yêu cầu mục 3 */}
      <div className="mb-6">
        <div className="mb-3 flex flex-wrap items-baseline justify-between gap-2">
          <h2 className="text-base font-bold text-ink-700">Tổng kết tuần</h2>
          {targetUserId === session.userId && (
            <Link href={`/cong-viec/chot-tuan?tuan=${monday}`} className="text-sm text-brand-600 hover:underline">
              Chốt tổng kết tuần này →
            </Link>
          )}
        </div>
        <WeeklySummaryView data={weekSummary} />
      </div>

      {/* KPI tự tạo — chỉ tiêu ngoài bộ số liệu cố định, do quản lý tự đặt và giao */}
      {customKpiRows.length > 0 && (
        <div className="mb-6">
          <SectionTitle hint={formatPeriod(monthKey(today()))}>KPI tự tạo</SectionTitle>
          <div className="grid gap-3 lg:grid-cols-2">
            {customKpiRows.map((kpi) => {
              const pct = kpi.targetValue > 0 ? (kpi.actualValue / kpi.targetValue) * 100 : null;
              const mine = yearEntries.filter((e) => e.kpiId === kpi.kpiId);
              const sum = (rows: typeof mine) => ({
                target: rows.reduce((t, e) => t + e.targetValue, 0),
                actual: rows.reduce((t, e) => t + e.actualValue, 0),
              });
              const quarter = sum(mine.filter((e) => quarterMonths.has(e.periodKey)));
              const year = sum(mine);
              const logs = kpiLogRows.filter((l) => l.entryId === kpi.id);
              const todaySum = logs.filter((l) => l.logDate === today()).reduce((t, l) => t + l.value, 0);
              const weekSum = logs.reduce((t, l) => t + l.value, 0);
              const pctOf = (r: { target: number; actual: number }) =>
                r.target > 0 ? `${Math.round((r.actual / r.target) * 100)}%` : "—";
              return (
                <div key={kpi.id} className="card p-4">
                  <div className="mb-2 flex items-baseline justify-between gap-2">
                    <span className="text-sm font-semibold text-ink-700">{kpi.name}</span>
                    <span className="tnum text-sm text-ink-400">
                      {kpi.actualValue} / {kpi.targetValue} {kpi.unit}
                    </span>
                  </div>
                  {pct != null && <ProgressBar percent={pct} benchmark={timePct} />}
                  {pct != null && (
                    <div className="mt-1 text-[11px] text-ink-400">
                      Đã đạt {Math.round(pct)}% chỉ tiêu tháng · đã qua {Math.round(timePct)}% thời gian —{" "}
                      {pct >= timePct ? "đang kịp tiến độ" : `cần thêm ${Math.max(0, Math.ceil((kpi.targetValue * timePct) / 100 - kpi.actualValue))} ${kpi.unit} để kịp tiến độ`}
                    </div>
                  )}
                  <div className="mt-2 flex flex-wrap gap-x-4 gap-y-1 text-xs text-ink-500">
                    <span>Hôm nay: <b className="tnum">{todaySum}</b></span>
                    <span>Tuần này: <b className="tnum">{weekSum}</b></span>
                    <span>Tháng: <b className="tnum">{pctOf({ target: kpi.targetValue, actual: kpi.actualValue })}</b></span>
                    <span>Quý: <b className="tnum">{quarter.actual}/{quarter.target} ({pctOf(quarter)})</b></span>
                    <span>Năm: <b className="tnum">{year.actual}/{year.target} ({pctOf(year)})</b></span>
                  </div>
                  {isOwnPlan && (
                    <ActionForm action={logKpiProgressAction} success="Đã ghi nhận." resetOnSuccess className="mt-3 flex flex-wrap items-end gap-2 border-t border-[var(--color-line)] pt-3">
                      <input type="hidden" name="entryId" value={kpi.id} />
                      <div>
                        <label className="label-caps mb-1 block">Hôm nay đã làm ({kpi.unit})</label>
                        <input name="value" type="number" min={0.01} step="any" required className="input tnum w-28" />
                      </div>
                      <div className="min-w-32 flex-1">
                        <label className="label-caps mb-1 block">Ghi chú</label>
                        <input name="note" className="input" placeholder="VD: 3 bác sĩ, 2 chủ spa" />
                      </div>
                      <button type="submit" className="btn-ghost">
                        Ghi nhận
                      </button>
                    </ActionForm>
                  )}
                  {logs.length > 0 && (
                    <ul className="mt-2 text-[11px] text-ink-400">
                      {logs.slice(0, 3).map((l, i) => (
                        <li key={i}>
                          {formatDate(l.logDate)} · +{l.value} {kpi.unit}
                          {l.note ? ` — ${l.note}` : ""}
                        </li>
                      ))}
                    </ul>
                  )}
                </div>
              );
            })}
          </div>
        </div>
      )}

      {!plan ? (
        <div className="mt-6 flex flex-col gap-3">
          <EmptyState
            message="Chưa có kế hoạch tuần này."
            hint="NVKD lập kế hoạch đầu tuần: ngày, nội dung, mục tiêu, thời gian và lộ trình tuyến."
          />
          {isOwnPlan && (
            <AddPlanItemForm days={[...days]} dayLabels={DAY_LABEL} customers={myCustomers} />
          )}
        </div>
      ) : (
        <div className="mt-6">
          <div className="mb-3 flex flex-wrap items-baseline justify-between gap-2">
            <SectionTitle hint={plan.objective ?? undefined}>Lộ trình tuyến trong tuần</SectionTitle>
            {isOwnPlan && (
              <AddPlanItemForm days={[...days]} dayLabels={DAY_LABEL} customers={myCustomers} />
            )}
          </div>
          <div className="grid gap-3 lg:grid-cols-2">
            {days.map((day, index) => {
              const dayItems = items.filter((i) => i.planDate === day);
              if (dayItems.length === 0) return null;
              return (
                <div key={day} className="card p-4">
                  <div className="mb-3 flex items-baseline justify-between">
                    <span className="text-sm font-bold text-ink-700">{DAY_LABEL[index]}</span>
                    <span className="tnum text-xs text-ink-400">{formatDate(day)}</span>
                  </div>
                  <ul className="flex flex-col gap-2.5">
                    {dayItems.map((item) => (
                      <li key={item.id} className="flex gap-3">
                        <span className="tnum w-20 shrink-0 pt-0.5 text-[11px] text-ink-400">
                          {item.timeSlot ?? "—"}
                        </span>
                        <div className="min-w-0 flex-1">
                          <div className="text-sm text-ink-700">{item.content}</div>
                          {item.customerName && (
                            <div className="text-[11px] text-ink-400">{item.customerName}</div>
                          )}
                          {item.objective && (
                            <div className="mt-0.5 text-[11px] text-ink-400">Mục tiêu: {item.objective}</div>
                          )}
                        </div>
                        <Badge
                          tone={
                            item.status === "DONE" ? "green" : item.status === "MISSED" ? "red" : "neutral"
                          }
                        >
                          {{ DONE: "Đã làm", MISSED: "Chưa đạt", PLANNED: "Kế hoạch" }[item.status]}
                        </Badge>
                      </li>
                    ))}
                  </ul>
                </div>
              );
            })}
          </div>
        </div>
      )}

      <div className="mt-6 grid gap-4 lg:grid-cols-2">
        <div>
          <SectionTitle hint="so với kế hoạch">Báo cáo kết quả hằng ngày</SectionTitle>
          {reports.length === 0 ? (
            <EmptyState message="Chưa có báo cáo ngày nào trong tuần." />
          ) : (
            <div className="flex flex-col gap-2">
              {reports.map((report) => (
                <div key={report.id} className="card p-4">
                  <div className="mb-1.5 flex flex-wrap items-center gap-2">
                    <span className="tnum text-sm font-bold text-ink-700">
                      {formatDate(report.reportDate)}
                    </span>
                    <Badge tone={report.completionPct >= 80 ? "green" : "gold"}>
                      Thực hiện {report.completionPct}%
                    </Badge>
                    {!report.routeCompliant && <Badge tone="red">Lệch lộ trình</Badge>}
                  </div>
                  {report.results && <p className="text-sm text-ink-600">{report.results}</p>}
                  {report.pending && (
                    <p className="mt-1.5 text-xs text-ink-500">
                      <span className="font-semibold">Tồn đọng:</span> {report.pending}
                    </p>
                  )}
                  {report.proposals && (
                    <p className="mt-1 text-xs text-ink-500">
                      <span className="font-semibold">Đề xuất:</span> {report.proposals}
                    </p>
                  )}
                </div>
              ))}
            </div>
          )}
        </div>

        <div>
          <SectionTitle hint="định vị thực tế tại điểm bán">Kiểm chứng đi thị trường</SectionTitle>
          {visits.length === 0 ? (
            <EmptyState
              message="Chưa có lượt check-in nào."
              hint="NVKD check-in bằng điện thoại khi tới điểm bán, hệ thống ghi lại vị trí và thời gian."
            />
          ) : (
            <>
            {/* Điện thoại: mỗi lượt check-in một thẻ. */}
            <div className="flex flex-col gap-2 md:hidden">
              {visits.map((visit) => (
                <div key={visit.id} className="card p-3">
                  <div className="flex items-start justify-between gap-3">
                    <div className="min-w-0 font-semibold text-ink-700">{visit.customerName ?? "—"}</div>
                    {visit.outOfRange ? (
                      <Badge tone="red">Ngoài phạm vi</Badge>
                    ) : (
                      <Badge tone="green">Hợp lệ</Badge>
                    )}
                  </div>
                  <div className="mt-1 flex items-center justify-between gap-3 text-xs text-ink-400">
                    <span>
                      {formatDateTime(visit.checkedAt)}
                      {visit.distanceMeters != null ? ` · lệch ${Math.round(visit.distanceMeters)} m` : ""}
                    </span>
                    {visit.photoPath && (
                      <a
                        href={`/api/anh/${visit.photoPath}`}
                        target="_blank"
                        rel="noreferrer"
                        className="shrink-0 font-medium text-brand-600"
                      >
                        Xem ảnh
                      </a>
                    )}
                  </div>
                </div>
              ))}
            </div>
            <div className="hidden md:block">
            <TableWrap>
              <thead>
                <tr>
                  <th>Thời điểm</th>
                  <th>Điểm bán</th>
                  <th className="text-right">Sai lệch</th>
                  <th>Trạng thái</th>
                  <th>Ảnh</th>
                </tr>
              </thead>
              <tbody>
                {visits.map((visit) => (
                  <tr key={visit.id}>
                    <td className="tnum whitespace-nowrap text-ink-500">
                      {formatDateTime(visit.checkedAt)}
                    </td>
                    <td className="text-ink-700">{visit.customerName ?? "—"}</td>
                    <td className="tnum text-right text-ink-500">
                      {visit.distanceMeters != null ? `${Math.round(visit.distanceMeters)} m` : "—"}
                    </td>
                    <td>
                      {visit.outOfRange ? (
                        <Badge tone="red">Ngoài phạm vi</Badge>
                      ) : (
                        <Badge tone="green">Hợp lệ</Badge>
                      )}
                    </td>
                    <td>
                      {visit.photoPath ? (
                        <a
                          href={`/api/anh/${visit.photoPath}`}
                          target="_blank"
                          rel="noreferrer"
                          className="text-brand-600 hover:underline"
                        >
                          Xem ảnh
                        </a>
                      ) : (
                        <span className="text-ink-300">—</span>
                      )}
                    </td>
                  </tr>
                ))}
              </tbody>
            </TableWrap>
            </div>
            </>
          )}
        </div>
      </div>
    </>
  );
}
